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

posted @ 2019-08-22 09:22  funforever  阅读(184)  评论(0编辑  收藏  举报