Description
The i’th Fibonacci number f(i) isrecursively defined in the followingway:
• f(0) = 0 and f(1) = 1• f(i + 2) = f(i + 1) + f(i)
for every i ≥ 0 Your task is to compute some values of this sequence.
Input
Input begins with an integer t ≤10, 000, the number of test cases.Each test case consists of three integers a, b, n where 0 ≤ a, b < 264(a and b will not both be zero) and1 ≤ n ≤ 1000.
Output
For each test case, output a single line containing the remainder of f(a^b) upon division by n.
Sample Input
3
1 1 2
2 3 1000
18446744073709551615 18446744073709551615 1000
Sample Output
1
21
250
即求斐波那契数列中第a^b项对m取余的余数。
注意到a,b非常大,上限在2^64,并且是正整数,所以应该用unsigned long long。
问题可以分解为几个小问题:首先,从第三个样例可以看到,a^b可以变得无比巨大,所以基本可以判断这是一个找规律的题目,再考虑到,任何一个数对m取模,最多有m种余数(包括0,即整除)。由于斐波那契通常是以递推方式给出,如果存在一个i,第i项对应的余数等于第一项对应的余数,第i+1项的余数对应第二项的余数,可以断定,接下来第i+2,i+3...项将重复第i项之前的余数的循环。
我们找到这个循环大小,接下来的任务就是判断(a^b) mod m 的值了。这个余数就指出了f(a^b)的余数是循环节中的第几项
求(a^b) mod m 就用到了快速幂,这是个分治思想,每次调用都近似地将问题规模减半,其复杂度为O(logN)
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<cstring>
#include<vector>
#include<string>
#include<cmath>
#include<stack>
//#define file
#define maxn 100010
#define inf 0x3f3f3f3f
using namespace std;
int t;
unsigned long long m,n;
int mod;
unsigned long long ans[1000000];
int num[1010];
void init(int i)
{
ans[0]=0%i;
ans[1]=1%i;
int j=2;
while(j)
{
ans[j]=(ans[j-1]%i+ans[j-2]%i)%i;
if(ans[j]==ans[1]&&ans[j-1]==ans[0])
{
num[i]=j-1;
break;
}
j++;
}
}
int qu_mod(unsigned long long a,unsigned long long b,int m)
{
int ans=1;
while(b)
{
if(b&1)
ans=(int)((ans*a)%m);
a=(a*a)%m;
b>>=1;
}
return ans;
}
int main()
{
scanf("%d",&t);
//init();
while(t--)
{
scanf("%llu%llu%d",&m,&n,&mod);
if(m==0||mod==1)
{
printf("0\n");
}
else
{
init(mod);
int tmp=qu_mod(m%num[mod],n,num[mod]);
/*for(int i=0; i<=1000; i++)
{
cout<<ans[i]<<" ";
if(i%10==0)cout<<endl;
if(i%100==0)
cout<<"*****************"<<endl;
if(ans[i]==250)
cout<<"####"<<i+1<<endl;
}*/
printf("%d\n",ans[tmp]);
}
}
}