HDU1757
解题思路:分析需要不少时间,比较懒,直接把别人的分析贴在这里,
然后贴上自己写的代码:
K相当之大。所以逐一递推的算法无法胜任。这时我们就不得不运用矩阵加速。首先来讲一下矩阵乘法:
若一矩阵的列数与另一矩阵的行数相等,则可定义这两个矩阵的乘积。如 A 是 m×n 矩阵和 B 是 n×p矩阵,它们是乘积 AB 是一个
m×p 矩阵,其中
(AB)[i, j] = A[i, 1] * B[1, j] + A[i, 2] * B[2, j] + ... + A[i, n]
* B[n, j] 对所有 i 及 j。
此乘法有如下性质:
(AB)C = A(BC) 对所有 k×m 矩阵 A, m×n 矩阵 B 及 n×p 矩阵 C ("结合律").
(A + B)C = AC + BC 对所有 m×n 矩阵 A 及 B 和 n×k 矩阵 C ("分配律")。
C(A + B) = CA + CB 对所有 m×n 矩阵 A 及 B 和 k×m 矩阵 C ("分配律")。
要注意的是:可置换性不一定成立,即有矩阵 A 及 B 使得 AB ≠ BA。
下面我们研究一下这道题如何运用矩阵。
f(x) = a0 *
f(x-1) + a1 * f(x-2) + a2 * f(x-3) + …… + a9 * f(x-10)
构造的矩阵是:
|0
1 0 .........
0|
|f0|
|f1 |
|0 0 1 0 .......
0| |f1|
|f2 |
|................1| * |..| =
|...|
|a9 a8
.........a0|
|f9|
|f10|
*/
我们看到规律了,每次要到下次个A*B,以此类推则由A*A*A.......A*B;
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int maxn = 15; 6 int k, mod; 7 8 struct MT{ 9 int m[maxn][maxn]; 10 }; 11 12 MT Mul(MT a, MT b) 13 { 14 MT res; 15 memset(res.m, 0, sizeof(res.m)); 16 17 for(int i = 0; i < 10; i++) 18 { 19 for(int j = 0; j < 10; j++) 20 { 21 for(int k = 0; k < 10; k++) 22 { 23 res.m[i][j] += a.m[i][k]*b.m[k][j] % mod; 24 } 25 res.m[i][j] %= mod; 26 } 27 } 28 return res; 29 } 30 31 MT Product(MT a, int k) 32 { 33 MT r; 34 memset(r.m, 0, sizeof(r.m)); 35 for(int i = 0; i < 10; i++) 36 { 37 r.m[i][i] = 1; 38 } 39 40 while(k) 41 { 42 if(k & 1) r = Mul(r, a); 43 k >>= 1; 44 a = Mul(a, a); 45 } 46 47 return r; 48 } 49 50 int main() 51 { 52 MT a; 53 while(~scanf("%d %d", &k, &mod)) 54 { 55 for(int i = 0; i < 9; i++) 56 { 57 for(int j = 0; j < 10; j++) 58 { 59 if(j == i + 1) a.m[i][j] = 1; 60 else a.m[i][j] = 0; 61 } 62 } 63 64 for(int i = 9; i >= 0; i--) 65 { 66 scanf("%d", &a.m[9][i]); 67 } 68 69 if(k <= 9) 70 { 71 printf("%d\n", k % mod); 72 continue; 73 } 74 75 int ans = 0; 76 MT b = Product(a, k-9); 77 78 for(int i = 0; i < 10; i++) 79 { 80 ans += b.m[9][i]*i % mod; 81 } 82 83 printf("%d\n", ans % mod); 84 } 85 return 0; 86 }