POJ3233 Matrix Power Series题解和感想
Matrix Power Series
Time Limit: 3000MS | Memory Limit: 131072K | |
Total Submissions: 31485 | Accepted: 12686 |
Description
Given a n × n matrix A and a positive integer k, find the sum S = A + A2 + A3 + … + Ak.
Input
The input contains exactly one test case. The first line of input contains three positive integers n (n ≤ 30), k (k ≤ 109) and m (m < 104). Then follow n lines each containing n nonnegative integers below 32,768, giving A’s elements in row-major order.
Output
Output the elements of S modulo m in the same way as A is given.
Sample Input
2 2 4 0 1 1 1
Sample Output
1 2 2 3
这是一道某矩阵题,明眼人一看就知道k<=109就知道用快速幂,但是你一看到S这个公式,尼玛,什么鬼,累加?109累个鸡儿。怎么办?还得快速幂。这个快速幂我们可以参考北大某ppt:
怎么样,是不是恍然大悟,恍然大悟,恍然大悟了,S(n / 2)怎么求,继续二分嘛,这样就很简单了,但是要注意范围以及取模(注意防止相乘的时候超出范围),以及最最最最最最最重要的,矩阵乘法中两个矩阵相乘顺序不一样,结果也就不一样(A*B != B*C)!!!!!!!!!!!!!!!!!!!!!
于是乎我们有
#include <stdio.h> #include <string.h> int n, k, m; struct matrix{ int a[30][30]; matrix(){memset(a, 0, sizeof(a));}//记得初始化结构体 friend matrix operator%(matrix a, int m){//重载% for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) a.a[i][j] %= m; return a; } friend matrix operator*(matrix a, matrix b){//重载* matrix c; for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) for(int k = 0; k < n; k++) c.a[i][j] += (a.a[i][k] * b.a[k][j]) % m; return c % m; } friend matrix operator+(matrix a, matrix b){//重载+ matrix c; for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) c.a[i][j] = (a.a[i][j] + b.a[i][j]) % m; return c % m; } }ans, single, unit;//unit为单位矩阵,single为A矩阵 matrix Pow(int n) { if(n == 1) return single % m; matrix t = Pow(n / 2); if(n % 2) return (t * t % m * (single % m)) % m; else return t * t % m; } matrix PowSumMod(int n)//注意奇数(n-1)/2和n/2结果一样,所以我们都用n/2 { if(n == 1) return single % m; if(n % 2 == 0) return (unit + Pow(n / 2)) % m * PowSumMod(n / 2); else return ((unit + Pow(n / 2)) % m * PowSumMod(n / 2) % m + Pow(n) % m) % m; } int main(void) { for(int i = 0; i < 30; i++)//初始化单位矩阵 unit.a[i][i] = 1; scanf("%d %d %d", &n, &k, &m); for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) scanf("%d", &single.a[i][j]); ans = PowSumMod(k); for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) { if(j != n - 1) printf("%d ", ans.a[i][j]); else printf("%d\n", ans.a[i][j]); } return 0; }
为什么要初始化结构体,因为我所有的结构体类型不都是开在全局的,所以如果不清零的话(WA了好几次)