GCJ Japan 2011 Final B. Multiplication of Bacteria
Problem Description:
There are T standalone test cases in this problem.
In the beginning, there are A units of bacteria.
For any moment t with x units of bacteria, we know that moment t + 1 would have x**x units of bacteria.
Given A, B, C, you are interested at the number of units of bacteria at moment B, modulo C.
Constraints:
Solution:
Let denote the number of units of bacteria at moment i.
Let denote .
Essentially, we are interested at .
The transition can be derived by the following:
We know that under any equivalence system with some fixed modulo, the series must form some cycle, and some non-negative length of head that precedes the entering of cycle.
We can precompute for each possible v and mod, and construct a table with each of the corresponding length of head and cycle.
With such values, by removing unnecessary loops, we can reduce the power in the previous equation to a computable extent.
Code:
#include <bits/stdc++.h> const int MAXA = 1000; const int MAXB = 1000; const int MAXC = 1000; int cyc[MAXC][MAXC + 1]; int hed[MAXC][MAXC + 1]; int nc[MAXA + 1][MAXB + 1]; int dp[MAXB + 1][MAXC + 1]; int int_pow(int v, int e, int m) { if (v == 0 || m == 1) return 0; int r = 1; for (int i = e; i; i >>= 1) { if (i & 1) (r *= v) %= m; (v *= v) %= m; } return r; } int naive_calc(int a, int b, int *nca) { if (b == 0) return nca[b] = a; int v = naive_calc(a, b - 1, nca); if (v == MAXC) return nca[b] = MAXC; int r = 1; for (int i = v; i; i >>= 1) { if (i & 1) r *= v; if (r > MAXC) return nca[b] = MAXC; v *= v; if (v > MAXC) return nca[b] = MAXC; } return nca[b] = r; } int solve(int a, int b, int c) { if (b == 0) return a % c; if (~dp[b][c]) return dp[b][c]; int v = solve(a, b - 1, c); int e; if (nc[a][b - 1] >= hed[v][c]) { e = solve(a, b - 1, cyc[v][c]); e = (e - hed[v][c] % cyc[v][c] + cyc[v][c]) % cyc[v][c] + hed[v][c]; // ensure that it goes into the cycle, because it might get chopped of, e.g., head = 3, cycle = 5, solve = 5, then we will access some element that is not even in the cycle, obviously leading to something wrong } else { e = nc[a][b - 1]; } return dp[b][c] = int_pow(v, e, c); } signed main() { for (int i = 0; i < MAXC; ++i) { for (int j = 1; j <= MAXC; ++j) { std::vector<int> vis(MAXC, -1); int ctr = 0; for (int u = 1; ; (u *= i) %= j) { if (~vis[u]) { cyc[i][j] = ctr - vis[u]; hed[i][j] = vis[u]; break; } vis[u] = ctr++; } } } for (int i = 1; i <= MAXA; ++i) { naive_calc(i, MAXB, nc[i]); } std::ios::sync_with_stdio(false); int T; std::cin >> T; for (int kase = 1; kase <= T; ++kase) { std::memset(dp, 0xff, sizeof(dp)); int A, B, C; std::cin >> A >> B >> C; std::cout << "Case #" << kase << ": " << solve(A, B, C) << std::endl; } return 0; }