/* *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 }