摘自: http://acm.hrbust.edu.cn/hcpc2012/index.php?act=showpost&p=15
本題是動(dòng)態(tài)規(guī)劃 + 矩陣乘法題
定義 f[i][0] 為走了 i 步恰好達(dá)到 S 的不同走法
定義 f[i][1] 為走了 i 步恰好達(dá)到 A 的不同走法
定義 f[i][2] 為走了 i 步恰好達(dá)到 B 的不同走法
定義 f[i][3] 為走了 i 步恰好達(dá)到 C 的不同走法
狀態(tài)轉(zhuǎn)義方程為:
f[i][0] = f[i – 1][1] + f[i – 1][2] + f[i – 1][3];
f[i][1] = f[i – 1][0] + f[i – 1][2] + f[i – 1][3];
f[i][2] = f[i – 1][0] + f[i – 1][1] + f[i – 1][3];
f[i][3] = f[i – 1][0] + f[i – 1][1] + f[i – 1][2];
由于 n 的規(guī)模達(dá)到 10 9 ,所以我們可以令
矩陣 A = [1 0 0 0] 表示走了 0 步時(shí)恰好到達(dá) S, A, B, C 的不同走法,
那么每次狀態(tài)轉(zhuǎn)義相當(dāng)于乘以矩陣 B ,其中:
B = [ 0 1 1 1
?????? 1 0 1 1
?????? 1 1 0 1
?????? 1 1 1 0 ]
可知,求走 n 步恰好到達(dá) S 點(diǎn)的不同走法即是求 A * B n ,使用矩陣快速冪乘法即可。
?
1 /* 2 * 動(dòng)態(tài)規(guī)劃+矩陣乘法 3 */ 4 5 #include <cstdio> 6 #include <cstdlib> 7 #include <iostream> 8 9 using namespace std; 10 11 const int M = 1000000007 ; 12 13 void martix(unsigned long long a[ 4 ][ 4 ],unsigned long long b[ 4 ][ 4 ]) { 14 unsigned long long c[ 4 ][ 4 ]; 15 int i, j, k; 16 for (i= 0 ; i< 4 ; ++ i) { 17 for (j= 0 ; j< 4 ; ++ j) { 18 c[i][j] = 0 ; 19 for (k= 0 ; k< 4 ; ++k) c[i][j] += a[i][k] * b[k][j] % M; 20 } 21 } 22 for (i= 0 ; i< 4 ; ++ i) { 23 for (j= 0 ; j< 4 ; ++j) a[i][j] = c[i][j]; 24 } 25 } 26 27 unsigned long long exp(unsigned long long cs[ 4 ][ 4 ], unsigned long long s[ 4 ][ 4 ], unsigned long long n) { 28 while (n) { 29 if (n & 1 ) martix(cs, s); 30 n >>= 1 ; 31 martix(s, s); 32 } 33 return cs[ 0 ][ 0 ] % M; 34 } 35 36 int main() { 37 int t; 38 scanf ( " %d " , & t); 39 while (t-- ) { 40 int n; 41 scanf ( " %d " , & n); 42 unsigned long long cs[ 4 ][ 4 ] = { 43 { 1 , 0 , 0 , 0 }, 44 { 0 , 1 , 0 , 0 }, 45 { 0 , 0 , 1 , 0 }, 46 { 0 , 0 , 0 , 1 }, 47 }; 48 unsigned long long s[ 4 ][ 4 ] = { 49 { 0 , 1 , 1 , 1 }, 50 { 1 , 0 , 1 , 1 }, 51 { 1 , 1 , 0 , 1 }, 52 { 1 , 1 , 1 , 0 }, 53 }; 54 unsigned long long ans = exp(cs, s, n); 55 printf ( " %llu\n " , ans); 56 } 57 return 0 ; 58 }
?
?
?
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
