评测地址:http://acm.hust.edu.cn/vjudge/problem/41990
1 The i'th Fibonacci number f (i) is recursively de ned in the following way: 2 3 f (0) = 0 and f (1) = 1 4 5 f (i + 2) = f (i + 1) + f (i) for every i 0 6 7 Your task is to compute some values of this sequence. 8 9 Input 10 11 Input begins with an integer t 12 10; 000, the number of test cases. 13 14 Each test case consists of three in-tegers a, b, n where 0 a; b < 264 (a and b will not both be zero) and 1 n 1000. 15 16 Output 17 18 For each test case, output a single line containing the remainder of f (ab) upon division by n. 19 20 Sample Input 21 22 3 23 1 1 2 24 2 3 1000 25 18446744073709551615 18446744073709551615 1000 26 27 Sample Output 28 29 1 30 21 31 250
题目大意:
输入两个非负整数a,b和正整数n(0<=a,b<2^64,1<=n<=1000),你的任务是计算f(a^b)除以n的余数。其中f(0)=f(1)=1,且对于所有非负整数i,f(i+2)=f(i+1)+f(i)。
解题思路:
这么大的数字,直接算是不现实的。
此时我们会想,要是f(i)% n能出现循环多好啊。
我们取F(i)=f(i) % n。若(F(i-1),F(i))出现重复,则整个序列将开始重复。 比如n=3时 1,1,2,0,2,2,1,0,1,1,2,0,2,2… 因为余数最多有n种可能,所以最多到第n^2项,就会出现重复,开始循环。 所以我们先花至多O(n^2)的时间处理一下找到循环节,再判断一下F(a^b)具体等于哪一项即可。
AC代码:
#include<cstdio> #include<iostream> #define ll unsigned long long using namespace std; const int N=1e6+100; int T,n,mod,f[N]={0,1,1}; ll a,b; int kpow(ll a,ll p){ int ans=1; for(;p;p>>=1,a=(a*a)%mod) if(p&1) ans=(ans*a)%mod; return ans; } int main(){ cin>>T; while(T--){ cin>>a>>b>>n; if(n==1||!a){printf("0 ");continue;} for(int i=3;i<=n*n+10;i++){ f[i]=(f[i-1]+f[i-2])%n; if(f[i]==f[2]&&f[i-1]==f[1]){mod=i-2;break;} } printf("%d ",f[kpow(a%mod,b)]); } return 0; }