问题 D: 【例题4】佳佳的Fibonacci
时间限制: 1 Sec 内存限制: 128 MB
提交: 2 解决: 1
[提交][状态][讨论版][命题人:quanxing]
题目描述
佳佳对数学,尤其数列十分感兴趣,在研究Fibonacci之后,他创造出许多稀奇古怪的数列。如求S(n)表示Fibonacci数列前n项和对m取模之后的值,即S(n)=(F1+F2+...+Fn)mod m,F1=F2=1。可是这对佳佳来说还是小菜一碟。终于,他找到一个自己解决不了的数列。T(n)表示Fibonacci数列前n项变形后的和对m取模之后的值,
即T(n)=(F1+2×F2+3×F3+...+n*Fn)mod m,F1=F2=1。
输入
第一行,包含两个整数n和m。1<=n,m<=2的31次方-1
输出
共一行,T(n)的值
样例输入
5 5
样例输出
1
与前两题类似,不过这题的递推式比较难求
(1) t[n]=f[1]+2*f[2]+3*f[3]+...+n*f[n]
(2) n*s[n]=n*f[1]+n*f[2]+n*f[3]+...+n*f[n]
(2)-(1),得
(3) n*s[n]-t[n]=(n-1)*f[1]+(n-2)*f[2]+...+f[n-1]
令p[n]=n*s[n]-t[n]---------------------------------------------------->t[n]=n*s[n]-p[n]
p[n+1]=p[n]+s[n]
p[n+1]=1*p[n]+1*s[n]+0*f[n+1]+0*f[n]
s[n+1]=0*p[n]+1*s[n]+1*f[n+1]+0*f[n]
f[n+2]=0*p[n]+0*s[n]+1*f[n+1]+1*f[n]
f[n+1]=0*p[n]+0*s[n]+1*f[n+1]+0*f[n]
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
long long int n,m;
struct node
{
long long int g[5][5];
}f,res;
void init(node &x)
{
for(int i=1;i<=4;i++)
for(int j=1;j<=4;j++)
if(i==j)x.g[i][j]=1;
else x.g[i][j]=0;
}
void multiple(node &x,node &y,node &z)
{
memset(z.g,0,sizeof(z.g));
for(int i=1;i<=4;i++)
for(int j=1;j<=4;j++)
if(x.g[i][j])
{
for(int k=1;k<=4;k++)
{
z.g[i][k]+=x.g[i][j]*y.g[j][k];
if(z.g[i][k]>=m)z.g[i][k]%=m;
}
}
}
void quickpow(int k)
{
init(res);
node temp=f,t;
while(k)
{
if(k&1)
{
multiple(res,temp,t);
res=t;
}
multiple(temp,temp,t);
temp=t;
k>>=1;
}
}
long long int solve()
{
if(n==1)return 1;
quickpow(n-1);
long long int pn=res.g[1][1]*0+res.g[1][2]*1+res.g[1][3]*1+res.g[1][4]*1;
if(pn>=m)pn%=m;
long long int sn=res.g[2][1]*0+res.g[2][2]*1+res.g[2][3]*1+res.g[2][4]*1;
if(sn>=m)sn%=m;
long long int tn=(n*sn-pn+m)%m;
return tn;
}
int main()
{
scanf("%d%d",&n,&m);
memset(f.g,0,sizeof(f.g));
f.g[1][1]=1;
f.g[1][2]=1;
f.g[2][2]=1;
f.g[2][3]=1;
f.g[3][3]=1;
f.g[3][4]=1;
f.g[4][3]=1;
long long int ans=solve();
printf("%d\n",ans);
return 0;
}