题目大意:求斐波那契数列的第n项对p取余的值(n,p<10^9)
考察点:数论
思路分析:参考了http://xuyemin520.is-programmer.com/posts/26398.html。
构造一个2 x 2的矩阵,使得它乘以(a,b)得到的结果是(b,a+b)。每多乘一次这个矩阵,这两个数就会多迭代一次。那么,我们把这个2 x 2的矩阵自乘n次,再乘以(0,1)就可以得到第n个Fibonacci数了。不用多想,这个2 x 2的矩阵很容易构造出来:
接下来我们要做的就是将这个矩阵的(n-1)次幂算出来,再乘以初始矩阵 ,即(0 1)的转置就行了。
计算(n-1)次幂可以用快速幂
#include<stdio.h>
typedef struct juzhen{
long long a,b,c,d;
}juzhen;
juzhen jzmul(juzhen x,juzhen y,long long p)
{
juzhen t;
t.a=((x.a*y.a)%p+(x.b*y.c)%p)%p;
t.b=((x.a*y.b)%p+(x.b*y.d)%p)%p;
t.c=((x.c*y.a)%p+(x.d*y.c)%p)%p;
t.d=((x.c*y.b)%p+(x.d*y.d)%p)%p;
return t;
}
int main()
{
long long n,p;
while (scanf("%lld%lld",&n,&p)!=EOF)
{
n=n-2;
if (n==0) printf("1\n");
else if (n==-1) printf("1\n");
else if (n==-2) printf("0\n");
else{
juzhen q,ans;
q.a=1;q.b=1;q.c=1;q.d=0;
ans.a=1;ans.b=1;ans.c=1;ans.d=0;
while (n>0)
{
if (n%2==1) ans=jzmul(ans,q,p);
n=n/2;
q=jzmul(q,q,p);
}
printf("%lld\n",ans.a);}
}
return 0;
}