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了好几次)

浙公网安备 33010602011771号