广义斐波那契
与原来的斐波那契类似
递推的公式有所变化
如果直接线性递推,O(n)的复杂度,在很多题目中都会被卡,所以这时候就可以用矩阵吗快速幂复杂度是O(logn)的
比照普通的快速幂,矩阵快速幂就是一样的思路
ll quick_pow(ll a,ll b,ll p)
{
ll ans=1;
while (b)
{
if (b&1) ///b为奇数
ans=(ans*a)%p;
a=(a*a)%p; ///b为偶数
b>>=1;
}
return ans;
}
乘以
就可以得到
所以只要把
乘以的n-1次方就可以得到FN Fn+1,而矩阵快速幂就可以快速求出后面的矩阵的n-1次方
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7;
ll n,k;
struct Node {
ll a[101][101];
}ret,tmp;
Node chen(Node x,Node y)
{
Node D;
for (int i=1;i<=2;++i)
for (int j=1;j<=2;++j)D.a[i][j]=0;
for (int i=1;i<=2;++i)
for (int j=1;j<=2;++j)
for (int k=1;k<=2;++k)
D.a[i][j]=(D.a[i][j]%mod+(x.a[i][k]*y.a[k][j])%mod)%mod;///基本的矩阵乘法
return D;
}
Node quick_chen(ll b,Node z)
{
Node s=tmp;///首先要开个单位矩阵,保证开始的乘法不变
while (b)
{
if (b&1) s=chen(s,z);///b为奇数,更新s
z=chen(z,z);
b>>=1;
}
return s;
}
int main()
{
ll n;
scanf("%lld",&n);
tmp.a[1][1]=1ll;
tmp.a[2][2]=1ll;///2*2的单位矩阵
Node Z;
Z.a[1][2]=1ll;
Z.a[2][1]=1ll;
Z.a[2][2]=1ll;///初始化
Node Q=quick_chen(n-1,Z);///1 1
printf("%lld
",((Q.a[1][1]+Q.a[2][1])%mod*1ll*(Q.a[1][2]+Q.a[2][2])%mod)%mod);
return 0;
}
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll mod=1e9+7;
struct Node {
long long a[10][10];
Node(){
for (int i=1;i<=2;++i)
for(int j=1;j<=2;++j)
if(i==j) a[i][j]=1ll;
else a[i][j]=0;
}
}tmp;
Node chen(Node x,Node y)
{
Node D;
for (int i=1;i<=2;++i)
for (int j=1;j<=2;++j)D.a[i][j]=0;
for (int i=1;i<=2;++i)
for (int j=1;j<=2;++j)
for (int k=1;k<=2;++k)
D.a[i][j]=(D.a[i][j]%mod+(x.a[i][k]%mod*y.a[k][j]%mod)%mod)%mod;
return D;
}
Node quick_chen(long long b,Node z)
{
Node s=tmp;
while (b)
{
if (b&1) s=chen(s,z);
z=chen(z,z);
b>>=1;
}
return s;
}
int main()
{
ll b,c,p,q,n,m;
scanf("%lld%lld%lld%lld%lld%lld",&b,&c,&p,&q,&n,&m);///an=b*an-1+c*an-2 p=an-1 q=an-2 m=mod
mod=m;
Node Z;
Z.a[1][1]=0;
Z.a[1][2]=c%mod;
Z.a[2][1]=1ll;
Z.a[2][2]=b%mod;
Node Q=quick_chen(n-1,Z);///1 1
printf("%lld
",(Q.a[1][1]*p%mod+Q.a[2][1]*q%mod)%mod);
return 0;
}
当然按照之前的想法,斐波那契有着递推公式
给一个简单的证明