/*
*State:  2604    140MS    252K    2286 B    C++
*题目大意:
*        给一个长度为l的串,串中只有m跟f两种字符,可以组成2^l种,求
*        不含fmf跟fff的数量。
*解题思路:
*        这种题目一看就是求递推式的。递推式的求导过程值得体会,想象一下。
*        f(l)代表长度为l的满足条件的串的个数,如果结尾为m的话,数量为f(l-1),
*        如果结尾为f的话,那么前面只能是mf跟mm,mm可以由f(l-3)得来,而考虑
*        mf要考虑到mf的前面不能是f,否则就造成fmf不满足了。那么要把mf前面不是f
*        考虑进去,就是f(l-4)了。最终就是f(l) = f(l-1) + f(l-3) + f(l-4);
*        l的长度为(0 <= L <= 10^6),很大,一切递推式可以用矩阵来构造,用矩阵
*        时间就快很多了。(矩阵一般与mod分不开,嘿嘿)。
*解题感想;
*        不知道是不是下午天气太热,头脑发胀了,最后的矩阵求结果,硬是把其中两项
*        给忽略了,还查了好久,晚上一看就看出来了,汗~
*/
View Code
  1 #include <iostream>
  2 #include <cmath>
  3 #define maxn 5
  4 using namespace std;
  5 
  6 struct Mat
  7 {
  8     int m, n;
  9     int d[maxn][maxn];
 10     void init(int m, int n) 
 11     {
 12         this->m = m;
 13         this->n = n;
 14         memset(d, 0, sizeof(d));
 15     }
 16     void initE(int size)                              //生成单位阵
 17     {
 18         m = n = size;
 19         for(int i = 0; i < n; i ++)
 20         {
 21             for(int j = 0; j < n; j ++)
 22             {
 23                 d[i][j] = i==j;
 24             }
 25         }
 26     }
 27     Mat operator * (const Mat & mat) const
 28     {
 29         static Mat res;
 30         res.init(m, mat.n);
 31         for(int i = 0; i < res.m; i ++)
 32         {
 33             for(int k = 0; k < n; k ++)
 34             {
 35                 if(d[i][k]==0)    continue;
 36                 for(int j = 0; j < res.n; j ++)
 37                 {
 38                     res.d[i][j] += d[i][k] * mat.d[k][j];
 39                 }
 40             }
 41         }
 42         return res;
 43     }
 44     Mat mul_mod(const Mat & mat, int mod) const
 45     {
 46         static Mat res;
 47         res.init(m, mat.n);
 48         for(int i = 0; i < res.m; i ++)
 49         {
 50             for(int k = 0; k < n; k ++)
 51             {
 52                 if(d[i][k]==0)    continue;
 53                 for(int j = 0; j < res.n; j ++)
 54                 {
 55                     res.d[i][j]=(res.d[i][j]+d[i][k]*mat.d[k][j]) % mod;
 56                 }
 57             }
 58         }
 59         return res;
 60     }
 61     void pow_mod(int k, int mod)                      //this = this^k % mod;
 62     {
 63         static Mat a;
 64         a = *this;
 65         for(this->initE(n); k; k>>=1, a=a.mul_mod(a, mod))
 66             if(k&1)    *this=this->mul_mod(a, mod);
 67     }
 68     void view_mat()
 69     {
 70         for(int i = 0; i < m; i++)
 71         {
 72             printf("%d", d[i][0]);
 73             for(int j = 1; j < n; j++)
 74                 printf(" %d", d[i][j]);
 75             printf("\n");
 76         }
 77     }
 78 };
 79 
 80 int main(void)
 81 {    
 82 #ifndef ONLINE_JUDGE
 83     freopen("in.txt", "r", stdin);
 84 #endif
 85     int l, m;
 86     int al[6] = {0, 2, 4, 6, 9, 15};
 87     while(scanf("%d %d", &l, &m) == 2)
 88     {
 89         if(l <= 5)
 90         {
 91             printf("%d\n", al[l] % m);
 92             continue;
 93         }
 94         Mat a;
 95         a.init(5, 5);
 96         a.d[0][0] = a.d[0][2] = a.d[0][3] = 1;
 97         for(int i = 1; i < a.m; i++)
 98             a.d[i][i-1] = 1;
 99         a.pow_mod(l - 5, m);
100         int ans = (a.d[0][0] * al[5] + a.d[0][1] * al[4] + a.d[0][2] * al[3] + a.d[0][3] * al[2]
101                 + a.d[0][4] * al[1]) % m;
102         printf("%d\n", ans);
103     }    
104     return 0;
105 }
posted on 2012-08-04 00:20  cchun  阅读(209)  评论(0编辑  收藏  举报