大一刚开始接触ACM就买了《算法竞赛入门经典》这本书,当时只能看懂前几章,而且题目也没做,粗鄙地以为这本书不适合自己。等到现在快大三了再回过头来看,发现刘老师还是很棒的!
扯远了。。。
题意:问f[a^b]%n的值,f为斐波那契数。根据f[i]=f[i-1]+f[i-2]不难发现,当二元组(f[i],f[i-1])出现重复时,整个序列就开始重复了。如n=3,序列f[i]的前10项为
0,1,1,2,0,2,2,1,0,1
f[9]和f[10]与前两项一样。
那么周期会在哪出现呢?从n项中取2项为C(n,2),即最多有n*(n-1)/2种组合,最多n^2,2<=n<=1000。实际上远小于n^2。
此时找到了周期长度m,答案为f[(a^b)%m],a^b用快速幂解决。
坑点,2^64得用usingned long long存,格式是%llu;注意n=1时要输出0。
代码:
#include<stdio.h> #include<string.h> typedef unsigned long long ll; ll a,b; int n,m,f[1111*1111]; int pow(ll a,ll b,int mod){ int ans=1; while(b){ if(b&1) ans=(ans*a)%mod; a=(a*a)%mod; b>>=1; } return ans; } int main(){ int t; scanf("%d",&t); while(t--){ scanf("%llu%llu%d",&a,&b,&n); f[0]=0,f[1]=1%n; for(int i=2;;i++){ f[i]=f[i-2]+f[i-1]; f[i]%=n; if(f[i]==f[1]&&f[i-1]==f[0]){ m=i-1; break; } } int t=pow(a%m,b,m); printf("%d ",f[t]); } return 0; }