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;
}
$$Life \quad is \quad fantastic!$$