大致題意:輸入兩個非負整數a,b和正整數n。計算f(a^b)%n。其中f[0]=f[1]=1, f[i+2]=f[i+1]+f[i]. 即計算大斐波那契數再取模。
一開始看到大斐波那契數,就想到了矩陣快速冪,輸出等了幾秒鐘才輸出完,肯定會超時。因為所有計算都是要取模的,設F[i]=f[i] mod n。F[0]=F[1]=1。只要出現F[i]=F[i+1]=1,那麼整個序列就會重復。例如n=3,則序列為1,1,2,0,2,2,1,0,1,1……第九項和第十項都等於1,所以之後的序列都會重復。
至於多久會重復一次,這個沒法直接看出來。我的程序是一直判斷下去知道有相鄰地兩個1,這樣有點冒險,不過沒有超時。後來看了下劉汝佳的書,書上這樣說的:因為余數最多n種,所以最多n2項就會重復。這是一個結論嗎,我沒看懂,先記著吧。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
const int maxn=1000000+5;
typedef unsigned long long ull;
int modnum[maxn];
int Mod;
int powermod(ull a,ull b,int c)
{
ull ans=1;
a%=c;
while(b)
{
if(b&1)
ans=ans*a%c;
a=a*a%c;
b=b>>1;
}
return ans;
}
int main()
{
//freopen("in.txt","r",stdin);
int t;
ull a,b;
scanf("%d",&t);
while(t--)
{
scanf("%llu%llu%d",&a,&b,&Mod);
if(Mod==1 || a==0)
{
printf("0\n");
continue;
}
modnum[0]=modnum[1]=1;
int p=1;
for(int i=2;;i++)
{
modnum[i]=(modnum[i-1]+modnum[i-2])%Mod;
if(modnum[i]==1 && modnum[i-1]==1)
{
p=i-1;
break;
}
}
printf("%d\n",modnum[powermod(a,b,p)-1]);
}
return 0;
}