HDU 2604 矩阵快速幂

题目大意

给定长度为l的只有f,m两种字母 的序列,问不出现fff,fmf的序列个数有多少个

 

每次的下一个状态都与前一次状态的后两个字母有关

比如我令mm : 0 , mf : 1 , fm : 2 , ff : 3;

那么dp[i][j] 表示长度为i的序列最后由j状态结尾的总个数,当然 j 要大于2

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

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

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

dp[i][3] = dp[i-1][1]

根据这个递推关系,我们就能很容易地用动态规划解这道题目,然后就发现超时了 。。。

换个角度把dp值当作矩阵看 (dp[i][0] ,  dp[i][1] , dp[i][2] , dp[i][3]) = {{1 , 1 , 0 , 0} , {0 , 0 , 1, 1} , {1 , 0 , 0 ,0} , {0 , 0 ,1 , 0}} *(dp[i-1][0] ,  dp[i-1][1] , dp[i-1][2] , dp[i-1][3]) 

 

然后连续乘法上进行优化

while(n){

  if(n & 1) ~

  ~

  n>>=1

}

 1 #include <cstdio>

 2 #include <cstring>

 3 #include <iostream>

 4 using namespace std;

 5 int l , M;

 6 

 7 struct Matrix{

 8     int m[4][4];

 9     Matrix operator*(const Matrix &p)const {

10         Matrix tmp;

11         for(int i = 0 ; i < 4 ; i++)

12             for(int j = 0 ; j<4 ; j++){

13                 tmp.m[i][j] = 0;

14                 for(int k = 0 ; k<4 ; k++){

15                     tmp.m[i][j] += m[i][k] * p.m[k][j];

16                     tmp.m[i][j] %= M;

17                 }

18             }

19         return tmp;

20     }

21     void show(){

22         for(int i = 0 ; i<4 ; i++){

23             for(int j = 0 ; j<4 ; j++){

24                 printf("%d " , m[i][j]);

25             }

26             puts("");

27         }

28     }

29 };

30 

31 Matrix pow(Matrix a , int n)

32 {

33     Matrix tmp;

34     memset(tmp.m , 0 , sizeof(tmp.m));

35     //建立一个单位矩阵

36     for(int i = 0 ; i<4 ; i++)

37             tmp.m[i][i] = 1;

38 

39     while(n){

40         if(n & 1) tmp = tmp*a;

41         a = a * a;

42         n >>= 1;

43     }

44     return tmp;

45 }

46 

47 int main()

48 {

49     while(~scanf("%d%d" , &l , &M)){

50         if(l == 0) puts("0");

51         else if(l == 1) printf("%d\n" , 2%M);

52         else{

53             Matrix a;

54             a.m[0][0] = 1 , a.m[0][1] = 1 , a.m[0][2] = 0 , a.m[0][3] = 0;

55             a.m[1][0] = 0 , a.m[1][1] = 0 , a.m[1][2] = 1 , a.m[1][3] = 1;

56             a.m[2][0] = 1 , a.m[2][1] = 0 , a.m[2][2] = 0 , a.m[2][3] = 0;

57             a.m[3][0] = 0 , a.m[3][1] = 0 , a.m[3][2] = 1 , a.m[3][3] = 0;

58 

59             Matrix t = pow(a , l-2);

60 

61             int ans = 0;

62             int b[4] = {1 , 1 , 1 , 1};

63             for(int i = 0 ; i<4 ; i++)

64                 for(int j = 0 ; j<4 ; j++){

65                     ans += b[j] * t.m[j][i];

66                 }

67             printf("%d\n" , ans % M);

68         }

69     }

70     return 0;

71 }

 

你可能感兴趣的:(HDU)