POJ 3734 DP+矩阵乘法
题意:
给n个block涂4种颜色,要求其中red和green的block为偶数,其余随意。输出方案总数
思路:
递推,设dp[i][j][k] 表示前i个block ,有j个red,k个green,的方案总数
又因为j,k不是奇数就是偶数,可以简化j,k=1则表示奇数,j,k=0表示偶数
就可以递推了~
用矩阵递推更有效率~
def=
{{2,0,1,1},
{0,2,1,1},
{1,1,2,0},
{1,1,0,2}
}
ans[0]={0,1,0,0}
ans[i]=def^k*ans[i-1]
注意:矩阵乘法不满足交换律。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <iostream> 5 6 #define SIZE 110 7 #define mod 10007 8 9 using namespace std; 10 11 struct MT 12 { 13 int x,y; 14 int mt[SIZE][SIZE]; 15 }ans,def; 16 17 int n,tt; 18 19 inline MT operator *(MT a,MT b) 20 { 21 MT c; 22 memset(c.mt,0,sizeof c.mt); 23 c.x=a.x; c.y=b.y; 24 for(int i=1;i<=a.x;i++) 25 for(int j=1;j<=b.y;j++) 26 for(int k=1;k<=a.y;k++) 27 c.mt[i][j]=(c.mt[i][j]+(a.mt[i][k]%mod)*(b.mt[k][j]%mod))%mod; 28 return c; 29 } 30 31 void read() 32 { 33 scanf("%d",&n); 34 ans.mt[1][1]=ans.mt[3][1]=ans.mt[4][1]=0; ans.mt[2][1]=1; 35 ans.x=4; ans.y=1; 36 for(int i=1;i<=4;i++) 37 for(int j=1;j<=4;j++) 38 def.mt[i][j]=1; 39 for(int i=1;i<=4;i++) def.mt[i][i]=2; 40 def.mt[1][2]=def.mt[2][1]=def.mt[3][4]=def.mt[4][3]=0; 41 def.x=def.y=4; 42 } 43 44 void go() 45 { 46 while(n) 47 { 48 if(n&1) ans=def*ans; 49 def=def*def; 50 n>>=1; 51 } 52 printf("%d\n",ans.mt[2][1]); 53 } 54 55 int main() 56 { 57 scanf("%d",&tt); 58 while(tt--) 59 { 60 read(); 61 go(); 62 } 63 system("pause"); 64 return 0; 65 }
没有人能阻止我前进的步伐,除了我自己!