这是昨天上课ChesterKing dalao讲线代时的例题
当时看到这道题就觉得很水,记录一下后面两位的情况然后讨论一下转移即可
由于之前刚好在做矩阵题,所以常规的矩阵快速幂优化也很简单
好我们开始看题目
首先很容易考虑到所有的情况只和最后两位有关,所以我们设a,b,c,d表示结尾为10,11,01,00的方案数,然后每一次增加位数,都有新的a',b',c'd'这转移为:
-
a'=a
-
b'=b+c
-
c'=a+d
-
d'=a+d
然后这个就是尿性的矩阵优化了,我们可以稍加分析得出递推矩阵:
1 0 0 0
0 1 1 0
1 0 0 1
1 0 0 1
然后矩阵快速幂求之即可
CODE
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long LL;
const int N=5,mod=1e9+7;
LL n;
struct Matrix
{
int n,m;
LL a[N][N];
inline void Dt_init(void)
{
n=m=4; memset(a,0,sizeof(a));
a[1][2]=a[2][2]=a[2][3]=a[3][1]=a[3][4]=a[4][1]=a[4][4]=1;
}
inline void cri_init(void)
{
n=m=4; memset(a,0,sizeof(a));
a[1][1]=a[2][2]=a[3][3]=a[4][4]=1;
}
inline LL get_sum(void)
{
LL ans=0;
for (register int i=1;i<=n;++i)
for (register int j=1;j<=m;++j)
ans=(ans+a[i][j])%mod;
return ans;
}
};
inline Matrix mul(Matrix A,Matrix B)
{
Matrix C; C.n=A.n; C.m=B.m; memset(C.a,0,sizeof(C.a));
for (register int i=1;i<=C.n;++i)
for (register int j=1;j<=C.m;++j)
for (register int k=1;k<=A.m;++k)
C.a[i][j]=(C.a[i][j]+A.a[i][k]*B.a[k][j])%mod;
return C;
}
inline Matrix quick_pow(Matrix A,LL p)
{
Matrix T; T.cri_init();
while (p)
{
if (p%2) T=mul(T,A);
A=mul(A,A); p/=2;
}
return T;
}
int main()
{
scanf("%lld",&n); Matrix A; A.Dt_init();
if (n==1) { puts("2"); return 0; }
if (n==2) { puts("4"); return 0; }
A=quick_pow(A,n-2);
printf("%lld",A.get_sum());
return 0;
}