题目大意

给定长度为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 }

 

 posted on 2014-12-26 23:08  Love风吟  阅读(150)  评论(0编辑  收藏  举报