链接:
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2629
题意:
输入两个非负整数a、b和正整数n(0≤a,b<2^64,1≤n≤1000),你的任务是计算f(a^b)除以n的余数。
其中f(0)=0,f(1)=1,且对于所有非负整数i,f(i+2)=f(i+1)+f(i)。
分析:
所有计算都是对n取模的,设F(i)=f(i)%n。不难发现,当二元组(F(i), F(i+1))出现重复时,整个序列就开始重复。
多久会出现重复呢?因为余数最多n种,所以最多n*n项就会出现重复。实际测试出最多3001项左右就会出现重复。
所以只需计算出周期,然后算出F(a^b)对应于其中的哪一项即可。
代码:
1 #include <cstdio> 2 3 typedef unsigned long long ULL; 4 const int UP = 1000 + 5; 5 int f[UP][UP*3], period[UP]; 6 7 int qmod(ULL a, ULL b, ULL n) { // 快速幂模 8 a %= n; 9 ULL res = 1; 10 while(b) { 11 if(b & 1) res = res * a % n; 12 b >>= 1; 13 a = a * a % n; 14 } 15 return res; 16 } 17 18 int main() { 19 period[1] = 1; 20 for(int n = 2; n <= 1000; n++) { 21 f[n][0] = 0; f[n][1] = 1; 22 for(int i = 2; ; i++) { 23 f[n][i] = (f[n][i-1] + f[n][i-2]) % n; 24 if(f[n][i-1] == 0 && f[n][i] == 1) { 25 period[n] = i - 1; 26 break; 27 } 28 } 29 } 30 31 int T, n; 32 ULL a, b; 33 scanf("%d", &T); 34 while(T--) { 35 scanf("%llu%llu%d", &a, &b, &n); 36 int p = qmod(a, b, period[n]); 37 printf("%d\n", f[n][p]); 38 } 39 return 0; 40 }
原文地址:https://www.cnblogs.com/hkxy125/p/8819861.html
时间: 2024-10-07 13:18:17