1. 程式人生 > >Blocks [POJ3734] [矩陣快速冪]

Blocks [POJ3734] [矩陣快速冪]

輸出 one 個數字 cli code == fine ans aps

題意:

有長度為n的一排格子,每個格子裏面可以任意填入1,2,3,4四個數字,問1,2都為偶數個的方案

T組數據,每組數據一個n(<=1e9)

樣例輸入

2

1

2

樣例輸出

2

6

分析

設dp[i][0/1/2/3]分別為處理到第i個,1和2的個數分別為 全偶、1偶2奇、1奇2偶,全奇

那麽dp轉移方程為

dp[i][0]=2dp[i-1][0]+dp[i-1][1]+dp[i-1][2] 填的分別是 3/4 1 2

dp[i][1]=dp[i-1][0]+2dp[i-1][1]+dp[i-1][3] 填的分別是 2 3/4 1

dp[i][2]=dp[i-1][0]+2dp[i-1][2]+dp[i-1][3] 填的分別是 1 3/4 2

dp[i][3]=dp[i-1][1]+dp[i-1][2]+2dp[i-1][3] 填的分別是 1 2 3/4

我們發現dp[i][1]和dp[i][2]可以合並在一起

那麽將dp[i][1]和dp[i][2]合並為dp[i][1],dp[i][3]改為dp[i][2]

那麽dp轉移方程簡化為:(簡化方式為上面2式和3式相加,dp[i][1]和dp[i][2]替換為dp[i][1],dp[i][3]替換為dp[i][2])

dp[i][0]=2dp[i-1][0]+dp[i-1][1]

dp[i][1]=2dp[i-1][0]+2dp[i-1][1]+2dp[i-1][3]

dp[i][2]=dp[i-1][1]+2dp[i-1][2]

我們發現n=1e9直接推會T,所以就上矩陣快速冪,初始矩陣為

| 2 2 0 |

| 0 0 0 |

| 0 0 0 |

轉置矩陣為

| 2 2 0 |

| 1 2 1 |

| 0 2 2 |

代碼

技術分享圖片
 1 #include<set>
 2 #include<map>
 3 #include<queue>
 4 #include<stack>
 5 #include<cmath>
 6 #include<cstdio>
 7 #include<cstring>
 8 #include<iostream>
 9
#include<algorithm> 10 #define RG register int 11 #define rep(i,a,b) for(RG i=a;i<=b;++i) 12 #define per(i,a,b) for(RG i=a;i>=b;--i) 13 #define ll long long 14 #define inf (1<<29) 15 using namespace std; 16 ll T,n; 17 const ll mo=10007; 18 inline int read() 19 { 20 int x=0,f=1;char c=getchar(); 21 while(c<0||c>9){if(c==-)f=-1;c=getchar();} 22 while(c>=0&&c<=9){x=x*10+c-0;c=getchar();} 23 return x*f; 24 } 25 26 struct Mat{ 27 ll a[3][3]; 28 Mat(){memset(a,0,sizeof(a));} 29 inline ll * operator [] (const int x){return a[x];} 30 inline Mat operator *(Mat b) 31 { 32 Mat ans; 33 rep(i,0,2) rep(j,0,2) rep(k,0,2) 34 (ans[i][j]+=(a[i][k]*b[k][j]))%=mo; 35 return ans; 36 } 37 }; 38 39 void work() 40 { 41 Mat S,T; 42 S[0][0]=2,S[0][1]=2,S[0][2]=0, 43 T[0][0]=2,T[0][1]=2, 44 T[1][0]=1,T[1][1]=2,T[1][2]=1, 45 T[2][1]=2,T[2][2]=2; 46 while(n) 47 { 48 if(n&1)S=S*T; 49 T=T*T; 50 n>>=1; 51 } 52 printf("%lld\n",S[0][0]); 53 } 54 55 int main() 56 { 57 T=read(); 58 while(T--) 59 { 60 n=read(); 61 work(); 62 } 63 return 0; 64 }
View Code

Blocks [POJ3734] [矩陣快速冪]