摘自: http://acm.hrbust.edu.cn/hcpc2012/index.php?act=showpost&p=15
本題是動態(tài)規(guī)劃 + 矩陣乘法題
定義 f[i][0] 為走了 i 步恰好達到 S 的不同走法
定義 f[i][1] 為走了 i 步恰好達到 A 的不同走法
定義 f[i][2] 為走了 i 步恰好達到 B 的不同走法
定義 f[i][3] 為走了 i 步恰好達到 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ī)模達到 10 9 ,所以我們可以令
矩陣 A = [1 0 0 0] 表示走了 0 步時恰好到達 S, A, B, C 的不同走法,
那么每次狀態(tài)轉(zhuǎn)義相當于乘以矩陣 B ,其中:
B = [ 0 1 1 1
?????? 1 0 1 1
?????? 1 1 0 1
?????? 1 1 1 0 ]
可知,求走 n 步恰好到達 S 點的不同走法即是求 A * B n ,使用矩陣快速冪乘法即可。
?
1
/*
2
* 動態(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號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

