http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4973
ZOJ Problem Set - 3690
Code
poj 3734 Blocks
f[i][a][b](a,b=0/1)表示长度为i的序列,红绿颜色的奇偶情况分别为a,b。递推公式比较好写,答案就是f[n][0][0],后两维也可以用一个两位二进制数表示。可以发现F[0]={1,1,1,1},所以写起来也比较简洁。其实实现上不需要体现出状态,全是矩阵乘。
#include <iostream> #include <cstring> using namespace std; struct Matrix{ #define MAXN 4 #define MOD 10007 int x,y; long long data[MAXN][MAXN]; struct CannotMultiply{}; Matrix(int _x=0,int _y=0):x(_x),y(_y){ memset(data,0, sizeof(data)); } Matrix operator*(const Matrix& rig)const { if(y!=rig.x)throw CannotMultiply(); Matrix res; res.x=x; res.y=rig.y; for (int i=0;i<x;++i){ for (int j=0;j<rig.y;++j){ for (int k=0;k<y;++k){ res.data[i][j] += data[i][k]*rig.data[k][j]; res.data[i][j] %= MOD; } } } return res; } }; Matrix pow(Matrix A,int n){ Matrix res(A.x,A.y); for(int i=0;i<res.x;i++) res.data[i][i]=1; for(;n>0;n>>=1,A=A*A) if(n&1) res=res*A; return res; } int main() { Matrix f(4,4); for(int i=0;i<4;i++) for(int j=0;j<4;j++) f.data[i][j]=1; for(int i=0;i<4;i++){ f.data[i][i] =2; f.data[i][3-i]=0; } int T;cin>>T; while(T--){ int n; cin>>n; Matrix ans; ans=pow(f,n); cout<<ans.data[0][0]<<endl; } return 0; }