【SSL_1529 / luogu_P1962】裴波拉契数列II

裴波拉契数列II


题目链接:裴波拉契数列II
                  ~~~~~~~~~~~~~~~~~                  裴波拉契数列

解题思路

我们设两个个数列,分别为:
∣ f [ n − 2 ] f [ n − 1 ] ∣ \begin{vmatrix}f[n-2]&f[n-1]\end{vmatrix} f[n2]f[n1]
∣ 0 1 1 1 ∣ \begin{vmatrix}0 & 1\\1 &1\end{vmatrix} 0111
将他们相乘,得:
∣ f [ n − 1 ] f [ n − 2 ] + f [ n − 1 ] ∣ \begin{vmatrix}f[n-1]&f[n-2]+f[n-1]\end{vmatrix} f[n1]f[n2]+f[n1]


∣ f [ n − 1 ] f [ n ] ∣ \begin{vmatrix}f[n-1]&f[n]\end{vmatrix} f[n1]f[n]
根据矩阵乘法的交换律,我们可以用快速幂算出第二个矩阵的 n n n 次方
快速幂矩阵乘法详见:【模板】矩阵快速幂

code

#include<iostream>
#include<cstdio>
#include<cstring>
#define myc using
#define ak namespace
#define ioi std
#define int long long

myc ak ioi;

const int mod=1e9+7;

int n;
int a[3][3]={
    
    {
    
    },{
    
    0,0,1},{
    
    0,1,1}};
int ans[3][3];
int t[3][3];

void add()
{
    
    
	memset(t,0,sizeof(t));
	for(int i=1;i<=2;i++)
		for(int j=1;j<=2;j++)
			for(int k=1;k<=2;k++)
				t[i][j]=(t[i][j]+ans[i][k]*a[k][j]%mod)%mod;
	for(int i=1;i<=2;i++)
		for(int j=1;j<=2;j++)
			ans[i][j]=t[i][j];
}

void cf()
{
    
    
	memset(t,0,sizeof(t));
	for(int i=1;i<=2;i++)
		for(int j=1;j<=2;j++)
			for(int k=1;k<=2;k++)
				t[i][j]=(t[i][j]+a[i][k]*a[k][j]%mod)%mod;
	for(int i=1;i<=2;i++)
		for(int j=1;j<=2;j++)
			a[i][j]=t[i][j];
}

void ksm(int b)
{
    
    
	ans[1][1]=ans[2][2]=1;
	while(b)
	{
    
    
		if(b&1)
			add();
		cf();
		b>>=1;
	}
}

signed main()
{
    
    
	cin>>n;
	if(n==1||n==2)
	{
    
    
		cout<<1<<endl;
		return 0;
	}
	ksm(n-2);
	cout<<(ans[1][2]+ans[2][2])%mod;
}

猜你喜欢

转载自blog.csdn.net/SSL_guyixin/article/details/111058287