Description
已知斐波那契数列前几项(从第一项开始)为1,1,2,3,...
给出两个正整数N,P,求出斐波那契数列前N项的平方和对P取模的值。
Input
只有一行,包含两个正整数N,P.
Output
只输出一行一个非负整数,表示答案。
Sample Input
Sample Output
HINT
样例解释:
(12 + 12 + 22 +
32)%20 = 15%20 = 15
数据范围与约定:
对于100%的测试数据,满足1<= N <=1018, 0< P <1018.
注:斐波那契数列前N项平方和:f(n)=f(n)*f(n+1)
#include<stdio.h>
#include<string.h>
struct Edge
{
long long num[3][3];
}a;
long long n,p;
long long ksj(long long x,long long y)
{
long long ans=0;
while(y)
{
if(y%2)
ans=(ans+x)%p;
x=(x+x)%p;
y/=2;
}
return ans;
}
Edge play(Edge x,Edge y)
{
Edge idx;
memset(&idx,0,sizeof(idx));
for(int i=1;i<=2;i++)
for(int j=1;j<=2;j++)
for(int k=1;k<=2;k++)
idx.num[i][j]=(idx.num[i][j]+ksj(x.num[i][k],y.num[k][j]))%p;
return idx;
}
Edge power(Edge x,long long y)
{
if(y==1)
return x;
Edge idx=power(x,y/2);
idx=play(idx,idx);
if(y%2)
idx=play(idx,x);
return idx;
}
int main()
{
scanf("%lld%lld",&n,&p);
a.num[1][1]=1;
a.num[1][2]=1;
a.num[2][1]=1;
Edge idx=power(a,n-2);
Edge idx2=power(a,n-1);
printf("%lld",ksj(((idx.num[1][1]+idx.num[1][2])%p),(idx2.num[1][1]+idx2.num[1][2])%p));
}