题目描述
大家都知道 Fibonacci 数列吧,。
现在问题很简单,输入n 和mod ,求fn%mod 。
样例
输入
5 1000
输出
5
思路:这一题的数据范围比较大,所以直接求是肯定不行的,一定会炸,然后我们看一下有没有其他的方法
我们知道f[i]=1f[i-1]+1f[i-2],f[i-1]=1f[i-1]+0f[i-2]
根据这两个式子我们可以发现
进一步可以得到
这样我们最后求出矩阵第一行的结果就行了
代码:
#include<stdio.h>
#include<string.h>
typedef long long ll;
const int N=2;
int m;
struct node
{
ll a[4][4];
} f,g;
void get(node &p)//构造单位矩阵
{
for(int i=1; i<=N; i++)
{
for(int j=1; j<=N; j++)
{
if(i==j) p.a[i][j]=1;
else p.a[i][j]=0;
}
}
}
void get_x(node &x,node &y,node &t)//矩阵乘法
{
memset(t.a,0,sizeof(t.a));
for(int i=1; i<=N; i++)
{
for(int j=1; j<=N; j++)
{
ll ans=0;
//if(x.a[i][j])
{
for(int k=1; k<=N; k++)
{
ans+=x.a[i][k]*y.a[k][j];
}
t.a[i][j]=ans%m;
//printf("<<%d\n",ans);
}
}
}
}
void quick(int k)//矩阵快速幂
{
get(g);
node t,temp=f;
while(k)
{
if(k%2) get_x(g,f,t),g=t;
//printf("<<%d\n",k);
get_x(f,f,t), f=t;
k/=2;
}
}
ll solve(int n)
{
f.a[1][1]=1;
f.a[1][2]=1;
f.a[2][1]=1;
f.a[2][2]=0;
quick(n-2);
//printf("||\n");
ll ans=g.a[1][1]+g.a[1][2];//求出第一行结果
if(ans>=m) ans-=m;
return ans;
}
int main()
{
int n;
scanf("%d %d",&n,&m);
if(n<=2) printf("1\n");
else
{
printf("%lld\n",solve(n));
}
}