连续幂求和 [原]

  

方法一

O(logn)是由于每次还要计算

改进:

      

方法二

  

  

 1 /*
2 * n阶矩阵A, 求A+。。。+A^k, 结果模mod。
3 *
4 * 类比上式:(注意这里从A开始加(而不是1),故略有不同)
5 * m = {{f1}, {x}}
6 * m1 = {{1}, {0}}
7 * m2 = {{x, 0}, {0, x}}
8 *
9 * mm = {{f(r)}, {x^r}}
10 *
11 * facor = {{1+x^(r/2), 0}, {0, x^(r/2)}}
12 */
13
14
15 #include <cstdio>
16 #include <cstring>
17 using namespace std;
18
19 const int maxn = 30 + 2;
20
21 int n, k, mod;
22 int m[maxn*2][maxn],
23 m1[maxn*2][maxn*2], m2[maxn*2][maxn],
24 lastAns[maxn*2][maxn];
25
26 void getFactor(int a[][maxn], int ans[][maxn*2]){
27 memset(ans, 0, sizeof(int)*maxn*2*maxn*2);
28 for(int i=0; i<n; i++){
29 for(int j=0; j<n; j++){
30 ans[i][j] = ans[i+n][j+n] = a[n+i][j];
31 }
32 ans[i][i] = (ans[i][i] + 1) % mod;
33 }
34
35 }
36 void multiply(int a[][maxn*2], int b[][maxn], int ans[][maxn]){
37 memset(ans, 0, sizeof(m));
38 for(int i=0; i<2*n; i++)
39 for(int j=0; j<n; j++)
40 for(int t=0; t<2*n; t++){
41 ans[i][j] =(ans[i][j]+ a[i][t] * b[t][j]) % mod;
42 }
43 }
44 void add(int a[][maxn], int b[][maxn]){
45 for(int i=0; i<2*n; i++)
46 for(int j=0; j<n; j++)
47 b[i][j] = (a[i][j] + b[i][j]) % mod;
48 }
49
50
51 void cal(int r, int mm[][maxn]){
52 if(r==1){
53 memcpy(mm, m, sizeof(m));
54 return;
55 }
56 int tmpAns[maxn*2][maxn]={};
57 int factor[maxn*2][maxn*2]={};
58 if(r%2==0){
59 cal(r/2, tmpAns);
60 getFactor(tmpAns, factor);
61 multiply(factor, tmpAns, mm);
62 }
63 else{
64 cal(r-1, tmpAns);
65 multiply(m1, tmpAns, mm);
66 add(m2, mm);
67 }
68 }
69
70
71 int main(){
72 scanf("%d%d%d", &n, &k, &mod);
73 for(int i=0; i<n; i++)
74 for(int j=0; j<n; j++){
75 scanf("%d", &m[i][j]);
76 m[i][j] %= mod;
77 m[n+i][j] = m[i][j];
78 m2[i][j] = m1[i][j] = m1[n+i][n+j] = m[i][j];
79 }
80
81 cal(k, lastAns);
82
83 for(int i=0; i<n; i++){
84 for(int j=0; j<n; j++){
85 printf("%d ", lastAns[i][j]%mod);
86 }
87 printf("\n");
88 }
89 }



原文地址:https://www.cnblogs.com/longdouhzt/p/2368828.html