问题 C: 【例题3】Fibonacci前n项和
时间限制: 1 Sec 内存限制: 128 MB
提交: 5 解决: 2
[提交][状态][讨论版][命题人:quanxing]
题目描述
大家都知道Fibonacci数列吧,f[1]=1,f[2]=1,f[3]=2,f[4]=3...也就是f[n]=f[n-1]+f[n-2]。现在,问题很简单,输入n和m,求前n项和取模m。
输入
输入n和m
1<=n<=2 000 000 000
1<=m<=1 000 000 010
输出
输出前n项和取模m。
样例输入
5 1000
样例输出
12
本题与“Fibonacci第n项”方法类似
s[n]=1*s[n-1]+1*f[n]+0*f[n-1]
f[n+1]=0*s[n-1]+1*f[n]+1*f[n-1]
f[n]=0*s[n-1]+1*f[n]+0*f[n-1]
#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<=3;i++)
for(int j=1;j<=3;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<=3;i++)
for(int j=1;j<=3;j++)
if(x.g[i][j])
{
for(int k=1;k<=3;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 ret=res.g[1][1]*1+res.g[1][2]*1+res.g[1][3]*1;
if(ret>=m)ret%=m;
return ret;
}
int main()
{
scanf("%d%d",&n,&m);
f.g[1][1]=1;
f.g[1][2]=1;
f.g[1][3]=0;
f.g[2][1]=0;
f.g[2][2]=1;
f.g[2][3]=1;
f.g[3][1]=0;
f.g[3][2]=1;
f.g[3][3]=0;
long long int ans=solve();
printf("%d\n",ans);
return 0;
}