hrbustOJ 1375The Active Leyni(动态规划+矩阵乘法)

摘自:http://acm.hrbust.edu.cn/hcpc2012/index.php?act=showpost&p=15

本题是动态规划+矩阵乘法题

定义f[i][0]为走了i步恰好达到S的不同走法

定义f[i][1]为走了i步恰好达到A的不同走法

定义f[i][2]为走了i步恰好达到B的不同走法

定义f[i][3]为走了i步恰好达到C的不同走法

状态转义方程为:

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的规模达到109,所以我们可以令

矩阵A = [1 0 0 0]表示走了0步时恰好到达S, A, B, C的不同走法,

那么每次状态转义相当于乘以矩阵B,其中:

B = [0 1 1 1

       1 0 1 1

       1 1 0 1

       1 1 1 0]

可知,求走n步恰好到达S点的不同走法即是求A * Bn,使用矩阵快速幂乘法即可。

 

 1 /*

 2 * 动态规划+矩阵乘法 

 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 }

 

 

 

你可能感兴趣的:(Active)