关键是使用这个公式来消掉循环,证明见:AekdyCoin' Blog.
#include <iostream>
#include <fstream> #include <cstdlib> #include <cstring> #include <cmath> #include <cstdio> #include <vector> #include <list> #include <deque> #include <climits> #include <algorithm> #include <queue> #include <functional> using namespace std; #if 0 #define d64 "%lld" #else #define d64 "%I64d" #endif #define mp make_pair typedef long long LL; typedef pair<int, int> pii; typedef pair<LL, LL> pll; const double EPS = 1e-10; int phi[1100000]; LL n, P, a, b; void allPhi() { phi[1] = 1; int n = 1000000; for(int i = 2; i <= n; i++) { if(!phi[i]) { for(int j = i; j <= n; j += i) { if(!phi[j]) phi[j] = j; phi[j] = phi[j] / i * (i - 1); } } } } void print(int a, LL b) { printf("Case #%d: "d64"\n", a, b); } LL powMod(LL a, LL b, LL p) { LL ans = 1; LL tmp = a % p; while(b) { if(b & 1) ans = ans * tmp % p; tmp = tmp * tmp % p; b >>= 1; } return ans; } void mul(LL A[2][2], LL B[2][2], LL C[2][2], LL p) { for(int i = 0; i < 2; i++) { for(int j = 0; j < 2; j++) { A[i][j] = 0; for(int k = 0; k < 2; k++) { A[i][j] = (B[i][k] * C[k][j] + A[i][j]) % p; } } } } LL work() { LL B[2][2] = {1, 1, 1, 0}; LL C[2][2] = {1, 0, 0, 1}; LL D[2][2]; LL c = n - 3; while(c) { if(c & 1) { memcpy(D, C, sizeof(C)); mul(C, D, B, phi[P]); } c >>= 1; memcpy(D, B, sizeof(B)); mul(B, D, D, phi[P]); } LL x = (C[0][0] + C[0][1]) % phi[P]; LL y = (C[1][0] + C[1][1]) % phi[P]; x += phi[P], y += phi[P]; LL ans = 1; ans = powMod(a, y, P) * powMod(b, x, P) % P; return ans; } int main() { // freopen("input.txt", "r", stdin); int T; scanf("%d", &T); allPhi(); for(int loop = 1; loop <= T; loop++) { scanf(d64 d64 d64 d64, &a, &b, &P, &n); if(n <=50) { if(n == 1) { print(loop, a % P); } else if(n == 2) { print(loop, b % P); } else { LL x = 1, y = 1; for(int i = 0; i < n - 3; i++) { LL tmp = y; y += x; x = tmp; } LL ans = powMod(a, x, P) * powMod(b, y, P) % P; print(loop, ans); } } else { LL ans = work(); print(loop, ans); } } return 0; } |
* This source code was highlighted by YcdoiT. ( style: Wombat )