P4910 帕秋莉的手环

人话题面

给定一个有\(n\)个位置的环,每个位置可以填入\(1/0\),要求不能有相邻的\(1\)

多组数据\(T\leq 10,n\leq 10^{18}\)

思路

  • \(60pts\)

\(f[i][0/1]\)表示第\(i\)个位置是\(0/1\)的方案数

\(\begin{array}{l} \left\{\begin{matrix} f[i][1]=f[i-1][0]\\f[i][0]=f[i-1][1]+f[i-1][0]\end{matrix}\right.\end{array}\)

复杂度为\(O(Tn)\),期望得分\(60pts\)

  • \(100pts\)

考虑矩阵优化

\(\begin{bmatrix}f_{i-1,0}&f_{i-1,1}\end{bmatrix} \times \begin{bmatrix}1&1\\1&0\end{bmatrix} = \begin{bmatrix}f_{i,0}&f_{i,1}\end{bmatrix}\)

复杂度为\(O(Tlogn)\)期望得分\(100pts\)

\(code\)

/*
@ author:pyyyyyy
-----思路------

-----debug-------

*/
#include<bits/stdc++.h>
#define int long long 
using namespace std;
const int mod=1000000007;
struct Matrix
{
	int x[2][2];
}a,b,c;
Matrix operator * (const Matrix &a,const Matrix &b)
{
	Matrix c;
	memset(c.x,0,sizeof(c.x));
	for(int k=0;k<=1;++k)
		for(int i=0;i<=1;++i)
			for(int j=0;j<=1;++j)
				c.x[i][j]=(c.x[i][j]+a.x[i][k]%mod*b.x[k][j]%mod)%mod;
			
	return c;
} 
Matrix ksm(Matrix a,int b){
	Matrix ret;
	memset(ret.x,0,sizeof(ret));
	for(int i=0;i<=1;++i) ret.x[i][i]=1;
	while(b)
	{
		if(b&1) ret=(ret*a);
		a=(a*a);
		b>>=1;
	}
	return ret;
}
int T,n;
signed main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	cin>>T;
	while(T--)
	{
		cin>>n;
		int ans=0;
		memset(a.x,0,sizeof(a.x));
		a.x[0][0]=a.x[0][1]=a.x[1][0]=1;
		a=ksm(a,n-1);
		memset(b.x,0,sizeof(b.x));
		b.x[0][0]=1;b=b*a;
		ans=(ans+b.x[0][0]%mod+b.x[0][1])%mod;
		memset(c.x,0,sizeof(c.x));
		c.x[0][1]=1;c=c*a;
		ans=(ans+c.x[0][0])%mod;
		cout<<ans<<'\n';
	}
	return 0;
}
posted @ 2020-06-14 15:24  pyyyyyy  阅读(125)  评论(0编辑  收藏  举报