hdu 3221 (指數迴圈節)
阿新 • • 發佈:2019-01-25
x^k=x^(k%phi(p)+phi(p))%p( k>=phi(p))
#include <utility> #include <algorithm> #include <string> #include <cstring> #include <cstdio> #include <iostream> #include <iomanip> #include <set> #include <vector> #include <cmath> #include <queue> #include <bitset> #include <map> #include <iterator> using namespace std; #define clr(a,v) memset(a,v,sizeof(a)) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 const int INF = 0x7f7f7f7f; const int maxn = 1000002; const double pi = acos(-1.0); const double eps = 1e-10; const int mod = 1000000007; typedef long long LL; typedef pair<int, int> pii; typedef vector<LL> VI; typedef vector<VI> VVI; typedef vector<VVI> VVVI; int a, b, n, p; LL f[85] = { 1, 0, 1, 1, 2 }; LL g[85] = { 0, 1, 1, 2, 3 }; int phi[maxn + 10]; void init() { int i, j; for (i = 2; i <= maxn; ++i) phi[i] = i; for (i = 2; i <= maxn; ++i) { if (phi[i] == i) { for (j = i; j <= maxn; j += i) { phi[j] = phi[j] - phi[j] / i; } } } for (i = 4; i <= 45; ++i) { f[i] = f[i - 1] + f[i - 2]; g[i] = g[i - 1] + g[i - 2]; } } LL POW(LL a, LL b, int mod) { LL res = 1; while (b) { if (b & 1) res = res * a % mod; a = a * a % mod; b >>= 1; } return res; } VVI A, I, E; const int size = 2; VVI multi(const VVI &A, const VVI &B, int mod) { int i, j, k; VVI res = VVI(size, VI(size, 0)); for (i = 0; i < size; ++i) { for (j = 0; j < size; ++j) { for (k = 0; k < size; ++k) { res[i][j] += A[i][k] * B[k][j]; res[i][j] %= mod; } } } return res; } VVI cal(const VVI& A, LL k, int mod) { VVI res = E, t = A; while (k) { if (k & 1) res = multi(res, t, mod); t = multi(t, t, mod); k >>= 1; } return res; } LL go(int n, LL a, LL b, int p) { if (p == 1) return 0; LL ans = 0; if (n <= 40) { ans = POW(a, f[n], p); ans = ans * POW(b, g[n], p) % p; return ans; } int mod = phi[p]; VVI res = cal(A, n - 1, mod); LL t1 = res[0][1], t2 = res[0][0]; t1 += mod, t2 += mod; t1 = POW(a, t1, p); t2 = POW(b, t2, p); ans = t1 * t2 % p; return ans; } int main() { ios::sync_with_stdio(false); E = I = A = VVI(2, VI(2, 0)); E[0][0] = E[1][1] = 1; I[0][0] = I[0][1] = I[1][0] = 1; A = I; init(); int T, cas; scanf("%d", &T); for (cas = 1; cas <= T; ++cas) { scanf("%d%d%d%d", &a, &b, &p, &n); printf("Case #%d: %I64d\n", cas, go(n - 1, a, b, p)); } return 0; }