题意:
斐波那契数列f(0) = 0, f(1) = 1, f(n+2) = f(n+1) + f(n) (n ≥ 0)
输入a、b、n,求f(ab)%n
分析:
构造一个新数列F(i) = f(i) % n,则所求为F(ab)
如果新数列中相邻两项重复出现的话,则根据递推关系这个数列是循环的。
相邻两项所有可能组合最多就n2中,所以根据抽屉原理得到这个数列一定是循环的。
求出数列的周期,然后快速幂取模即可。
1 #include <cstdio> 2 #include <iostream> 3 using namespace std; 4 5 const int maxn = 1000 + 10; 6 typedef unsigned long long ULL; 7 int f[maxn][maxn * 6], period[maxn]; 8 9 int pow_mod(ULL a, ULL b, int n) 10 { 11 if(b == 0) return 1; 12 int k = pow_mod(a, b/2, n); 13 k = k * k % n; 14 if(b % 2 == 1) k = k * a % n; 15 return k; 16 } 17 18 int solve(ULL a, ULL b, int n) 19 { 20 if(a == 0 || n == 1) return 0; 21 int p = pow_mod(a % period[n], b, period[n]); 22 return f[n][p]; 23 } 24 25 int main(void) 26 { 27 freopen("11582in.txt", "r", stdin); 28 for(int n = 2; n < maxn; ++n) 29 { 30 f[n][0] = 0, f[n][1] = 1; 31 for(int i = 2; ; ++i) 32 { 33 f[n][i] = (f[n][i-2] + f[n][i-1]) % n; 34 if(f[n][i-1] == 0 && f[n][i] == 1) 35 { 36 period[n] = i - 1; 37 break; 38 } 39 } 40 } 41 42 ULL a, b; 43 int n, T; 44 scanf("%d", &T); 45 while(T--) 46 { 47 cin >> a >> b >> n; 48 printf("%d ", solve(a, b, n)); 49 } 50 51 return 0; 52 }