矩阵是干什么的呢?一句话来说就是,知道相邻两个函数的递推关系和第一个数,让你递推到第n个数。显然,如果n很大,那么一个一个递推过去是会超时的。所以矩阵就是用来解决这种快速递推的问题的。
比方说斐波那契数列就是一个递推的典型。
先丢题目链接:我是题目!
那么问题的关键就变成了如何找递推关系的中介矩阵temp了。如果题目告诉了你递推关系,题目就变得很简单了。但是告诉你递推关系大致可分为两类,一类是加法的递推,像斐波那契数列,temp矩阵的每个元素都是常数。另外一种,就是有乘法的递推关系了,这类关系一般需要凑出来,有时候隐晦的话也不是那么容易的。比如说上面题目中的I题,就是需要拼凑的。
总之先交代模板,先看H题。这题求矩阵sum(A)=A^1+A^2+A^3+...+A^n。方法的话是二分,左边这个式子如果n是偶数的话可以拆成(1+A^(n/2))*(A^1+A^2+...+A(n/2)),然后右边部分又可以递归,不断二分地递归即可。当然,如果n是奇数要再加上A^n;另外上面式子中的1在这里指的是同阶的单位矩阵。代码如下(也可以直接当做矩阵的模板了):
1 #include <stdio.h> 2 #include <algorithm> 3 #include <math.h> 4 #include <vector> 5 #include <map> 6 #include <set> 7 #include <iostream> 8 #include <string.h> 9 #pragma comment(linker, "/STACK:1024000000,1024000000") 10 using namespace std; 11 typedef long long ll; 12 typedef pair<int,int> pii; 13 const int mod = 10; 14 15 //int mod; 16 17 void add(int &a,int b) 18 { 19 a += b; 20 if(a < 0) a += mod; 21 //if(a >= mod) a -= mod; 22 a %= mod; 23 } 24 25 struct matrix 26 { 27 int e[50+5][50+5],n,m; 28 matrix() {} 29 matrix(int _n,int _m): n(_n),m(_m) {memset(e,0,sizeof(e));} 30 matrix operator * (const matrix &temp)const 31 { 32 matrix ret = matrix(n,temp.m); 33 for(int i=1;i<=ret.n;i++) 34 { 35 for(int j=1;j<=ret.m;j++) 36 { 37 for(int k=1;k<=m;k++) 38 { 39 add(ret.e[i][j],1LL*e[i][k]*temp.e[k][j]%mod); 40 } 41 } 42 } 43 return ret; 44 } 45 matrix operator + (const matrix &temp)const 46 { 47 matrix ret = matrix(n,m); 48 for(int i=1;i<=n;i++) 49 { 50 for(int j=1;j<=m;j++) 51 { 52 add(ret.e[i][j],(e[i][j]+temp.e[i][j])%mod); 53 } 54 } 55 return ret; 56 } 57 void getE() 58 { 59 for(int i=1;i<=n;i++) 60 { 61 for(int j=1;j<=m;j++) 62 { 63 e[i][j] = i==j?1:0; 64 } 65 } 66 } 67 }; 68 69 matrix qpow(matrix temp,int x) 70 { 71 int sz = temp.n; 72 matrix base = matrix(sz,sz); 73 base.getE(); 74 while(x) 75 { 76 if(x & 1) base = base * temp; 77 x >>= 1; 78 temp = temp * temp; 79 } 80 return base; 81 } 82 83 void print(matrix p) 84 { 85 int n = p.n; 86 int m = p.m; 87 for(int i=1;i<=n;i++) 88 { 89 for(int j=1;j<=m;j++) 90 { 91 printf("%d ",p.e[i][j]); 92 } 93 cout << endl; 94 } 95 } 96 97 matrix solve(matrix a, int k) 98 { 99 if(k == 1) return a; 100 int n = a.n; 101 matrix temp = matrix(n,n); 102 temp.getE(); 103 if(k & 1) 104 { 105 matrix ex = qpow(a,k); 106 k--; 107 temp = temp + qpow(a,k/2); 108 return temp * solve(a,k/2) + ex; 109 } 110 else 111 { 112 temp = temp + qpow(a,k/2); 113 return temp * solve(a,k/2); 114 } 115 } 116 117 int main() 118 { 119 int n,k; 120 while(scanf("%d%d",&n,&k)==2 && n) 121 { 122 matrix a = matrix(n,n); 123 for(int i=1;i<=n;i++) 124 { 125 for(int j=1;j<=n;j++) {scanf("%d",&a.e[i][j]);a.e[i][j] %= mod;} 126 // 这里矩阵的每个元素在输入以后就要mod一下,不然可能会因为输入的元素太大导致在后面爆int(?) 127 } 128 matrix ans = solve(a,k); 129 for(int i=1;i<=n;i++) 130 { 131 for(int j=1;j<=n;j++) 132 { 133 printf("%d%c",ans.e[i][j],j==n?'\n':' '); 134 } 135 } 136 puts(""); 137 } 138 }