Poj 3233 Matrix Power Series (线性代数_矩阵)

题目链接:http://poj.org/problem?id=3233


题目大意:给定一个n*n的方阵A,再给出k和m,问A^1 + A ^2 + A^3 + A... + A^k  = ?矩阵中的每个数都对m取余。


解题思路:由A^k可用二分思想联想到这题也可以用二分思想,假设:如果k % 2 == 0,那么先计算A^1 + ... A^(k / 2),,然后可知A^((k/2)+1)等于A^1 * A^(k / 2), 

A^((k/2)+2)等于A^2 * A^(k / 2),由此可得 A^1 + ... A^(k/2) = (A^1+...A^(k/2)) * ((A^(k/2) + E),后面+E表示(A^1+...A^(k/2)) * E.r如果k % 2 == 1,那么

 A^1 + ... A^(k/2) = A^k + (A^k-1+..A^1); 


测试数据:

2 2 4
0 1
1 1


2 1 1
0 1
1 2


2 2 10000
32768 32768
32768 32768


代码:

#include <stdio.h>
#include <string.h>
#define MAX 40


int n,m,arr[MAX][MAX];
struct Mat {

	int mat[MAX][MAX],size;
	Mat() {};
	Mat(int n) {

		size = n;
		memset(mat,0,sizeof(mat));
	}
	Mat(int arr[][MAX],int n) {

		size = n;
		for (int i = 0; i < n; ++i)
			for (int j = 0; j < n; ++j)
				mat[i][j] = arr[i][j];
	}


	friend Mat operator *(Mat a,Mat b);
	friend Mat operator +(Mat a,Mat b);
	friend Mat operator ^(Mat a,int k);
}E;
Mat operator *(Mat a,Mat b) {

	Mat c(n);
	for (int i = 0; i < c.size; ++i)
		for (int j = 0; j < c.size; ++j)
			for (int k = 0; k < c.size; ++k)
				if (a.mat[i][k] && b.mat[k][j])
					c.mat[i][j] = (c.mat[i][j] + a.mat[i][k] * b.mat[k][j]) % m;
	return c;
}
Mat operator +(Mat a,Mat b) {

	Mat c(n);
	for (int i = 0; i < c.size; ++i)
		for (int j = 0; j < c.size; ++j)
			c.mat[i][j] = (a.mat[i][j] + b.mat[i][j]) % m;
	return c;
}
Mat operator ^(Mat a,int k) {

	Mat c = E;
	while (k) {

		if (k & 1) c = c * a;
		a = a * a,k >>= 1;
	}
	return c;
}

Mat sum(Mat A,int k) {

	if (k == 1) return A;
	if (k & 1)  return sum(A,k-1) + (A^k);
	return sum(A,k/2) * ((A^(k / 2)) + E);
}


int main()
{
	int i,j,k;


	while (scanf("%d%d%d",&n,&k,&m) != EOF) {

		E.size = n;
		memset(E.mat,0,sizeof(E.mat));
		for (i = 0; i < E.size; ++i)
			E.mat[i][i] = 1;
		for (i = 0; i < n; ++i)
			for (j = 0; j < n; ++j)
				scanf("%d",&arr[i][j]),arr[i][j] %= m;
		
			
		Mat c(arr,n);
		c = sum(c,k);
		for (i = 0; i < n; ++i)
			for (j = 0; j < n; ++j)
				printf(j == n - 1? "%d\n" : "%d ",c.mat[i][j]%m);
	}
}

本文ZeroClock原创,但可以转载,因为我们是兄弟。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值