1 /* 2 题意:用1*2覆盖n*m的区域的方案数,n<=1000,m<=5 3 思路:枚举每层的状态,计算状态之间的转移。则dp[i][j]=sum(dp[i-1][k]*a[k][j])其中k为前一层状态,j为当前层状态。 4 状态之间的转移,可以枚举当前层的放置方案, 5 时间:2018.07.18 6 */ 7 #include <bits/stdc++.h> 8 using namespace std; 9 10 typedef long long LL; 11 const int MAXN=100005; 12 const LL MOD7 = 1e9+7; 13 14 int a[1<<5][1<<5]; 15 LL dp[1005][1<<5]; 16 int n,m; 17 18 void dfs(int state1,int state2,int state,int depth) 19 { 20 // printf("state1=%d state2=%d state=%d depth=%d\n",state1,state2,state,depth); 21 // printf("%d %d\n",(state&(1<<depth)), (state2&(1<<depth))); 22 if (depth==m) 23 { 24 if (state==(1<<m)-1) ++a[state1][state2]; 25 return ; 26 } 27 if ((state&(1<<depth))==0 && (state2&(1<<depth))!=0) dfs(state1,state2,state+(1<<depth),depth+1); 28 if ((state&(1<<depth))==0 && (state2&(1<<depth))==0) 29 { 30 if (depth+1<m && (state&(1<<(depth+1)))==0) dfs(state1,state2,state+(1<<depth)+(1<<(depth+1)),depth+1); 31 return; 32 } 33 if ((state&(1<<depth))!=0 && (state2&(1<<depth))!=0) return; 34 dfs(state1, state2, state, depth+1); 35 } 36 37 void init() 38 { 39 for (int i=0;i<(1<<m);++i) 40 { 41 for (int j=0;j<(1<<m);++j) 42 { 43 dfs(i,j,i,0); 44 } 45 } 46 // for (int i=0;i<(1<<m);++i) 47 // { 48 // for (int j=0;j<(1<<m);++j) 49 // { 50 // printf("%d ",a[i][j]); 51 // } 52 // printf("\n"); 53 // } 54 } 55 56 int main() 57 { 58 #ifndef ONLINE_JUDGE 59 freopen("test.txt","r",stdin); 60 #endif // ONLINE_JUDGE 61 scanf("%d%d",&n,&m); 62 init(); 63 LL ans=0; 64 dp[0][(1<<m)-1]=1; 65 for (int i=1;i<=n+1;++i) 66 { 67 for (int j=0;j<(1<<m);++j) 68 { 69 for (int k=0;k<(1<<m);++k) 70 { 71 dp[i][j]=(dp[i][j]+a[k][j]*dp[i-1][k])%MOD7; 72 } 73 } 74 } 75 printf("%lld\n",dp[n+1][0]); 76 return 0; 77 }