XDU 1111
对于一排n个正方形,有f(n)种方案达成目标,若第n个块是白色,则有f(n-1)种方案,若第n个块是黑色,则第n-1个块必为白色,那么有f(n-2)+n-2种方案。
则f(n)=f(n-1)+f(n-2)+n-2 。
写成矩阵形式:
(//img-blog.csdn.net/20161011211956406)
例如:(i,j)表示i个空涂j个的种类数
(9,2)=(7,1)+(6,1)+(5,1)+(4,1)+(3,1)+(2,1)+(1,1)
(9,3)=(7,2)+(6,2)+(5,2)+(4,2)+(3,2)
(9,4)=(7,3)+(6,3)+(5,3)
(9,5)=(7,4)
(8,2)=(6,1)+(5,1)+(4,1)+(3,1)+(2,1)+(1,1)
(8,3)=(6,2)+(5,2)+(4,2)+(3,2)
(8,4)=(6,3)+(5,3)
#include<cstdio> #include<cstring> typedef long long ll; const ll mod=1e9+7; struct Mat { ll mat[4][4]; }; Mat Mult(Mat a,Mat b) { Mat c; memset(c.mat,0,sizeof(c.mat)); for(int i=0;i<4;i++) for(int j=0;j<4;j++) for(int k=0;k<4;k++) c.mat[i][j]=(c.mat[i][j]+a.mat[i][k]*b.mat[k][j])%mod; return c; } Mat QMult(Mat a,ll b) { Mat c; for(int i=0;i<4;i++) for(int j=0;j<4;j++) c.mat[i][j]=i==j; while(b){ if(b&1) c=Mult(c,a); a=Mult(a,a); b>>=1; } return c; } int main() { ll n; while(~scanf("%lld",&n)) { Mat res; if(n==2) { puts("0"); continue; } else if(n==3) { puts("1"); continue; } memset(res.mat,0,sizeof(res.mat)); res.mat[0][0]=res.mat[0][1]=res.mat[0][2]=res.mat[1][0]=1; res.mat[2][2]=res.mat[2][3]=res.mat[3][3]=1; res=QMult(res,n-3); printf("%lld\n",(res.mat[0][0]+2*res.mat[0][2]+res.mat[0][3])%mod); } return 0; }