【POJ3233】【矩阵乘法】【快速幂】Matrix Power Series

传送门

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

题目大意

对于任意给定的 r r r阶方阵 A A A,求 S [ n ] = A + A 2 + A 3 + … + A n S[n]=A+A^2+A^3+…+A^n S[n]=A+A2+A3++An


解题思路

构造一个1*2的矩阵
J 1 = [ A n − 1 S [ n − 2 ] ] J_1 = \begin{bmatrix} A^{n-1} & S[n-2] \end{bmatrix} J1=[An1S[n2]]

构造一个2*2的矩阵 J 2 J_2 J2
使得 J 1 = [ A n − 1 S [ n − 2 ] ] ∗ J 2 = [ A n S [ n − 1 ] ] J_1 = \begin{bmatrix} A^{n-1} & S[n-2] \end{bmatrix} * J_2 =\begin{bmatrix} A^n & S[n-1] \end{bmatrix} J1=[An1S[n2]]J2=[AnS[n1]]

那么 J 2 = [ A E O E ] J_2=\begin{bmatrix} A & E\\ O &E \end{bmatrix} J2=[AOEE]
O:全零矩阵
E(单位矩阵):主对角线上是1(任何一个矩阵乘上单位矩阵都等于它本身)(随便列两个矩阵都可以验证的)

那么矩阵套矩阵怎么算呢,肯定不是矩阵乘法套矩阵乘法这么弱智啊~~(我就是那个弱智)~~
把矩阵拆开来,左上角是A,右上角和右下角是单位矩阵,左下角是全零矩阵,矩阵大小 ( n ∗ 2 ) ∗ ( n ∗ 2 ) (n*2)*(n*2) (n2)(n2)
n = 3 n=3 n=3为例
[ A 1 , 1 A 1 , 2 A 1 , 3 1 0 0 A 2 , 1 A 2 , 2 A 2 , 3 0 1 0 A 3 , 1 A 3 , 2 A 3 , 3 0 0 1 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 ] \begin{bmatrix} A_{1,1} & A_{1,2} & A_{1,3} & 1 & 0&0 \\ A_{2,1} & A_{2,2} & A_{2,3} & 0 & 1 &0 \\ A_{3,1} & A_{3,2} & A_{3,3} & 0 & 0 &1 \\ 0 & 0 & 0 & 1 & 0&0 \\ 0 & 0 & 0 & 0 & 1& 0\\ 0 &0 & 0 & 0 & 0 &1 \end{bmatrix} A1,1A2,1A3,1000A1,2A2,2A3,2000A1,3A2,3A3,3000100100010010001001


Code

#include <iostream>
#include <cstring>
#include <cstdio>
#define ll long long

using namespace std;

struct DT{
    
    
	ll n, m;
	ll aed[70][70];
}A, B, Bc;
ll n, Mod, k;

DT operator * (DT a, DT b){
    
    
	DT c;
	memset (c.aed, 0, sizeof (c.aed));
	c.n = a.n, c.m = b.m;
	for (int k = 1; k <= a.m; k++)
		for (int i = 1; i <= c.n; i++)
			for (int j = 1; j <= c.m; j++)
				c.aed[i][j] = (c.aed[i][j] + a.aed[i][k] * b.aed[k][j] % Mod) % Mod;
	return c;
}

void power (ll x){
    
    
	if (x == 1)
	{
    
    
		B = Bc;
		return;
	}
	power (x / 2);
	B = B * B;
	if (x % 2)
		B = B * Bc;
}

int main(){
    
    
	scanf ("%lld%lld%lld", &n, &k, &Mod);
	A.n = A.m = Bc.m = Bc.n = n * 2;
	//A = A 和 J1;J2 = Bc和B
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
		{
    
    
			scanf ("%lld", &A.aed[i][j]);
			Bc.aed[i][j] = A.aed[i][j];//J2的左上角是A数组
		}
	for (int i = 1; i <= n; i++)
		Bc.aed[i][i + n] = Bc.aed[i + n][i + n] = 1;//J2的右上角和右下角是单位矩阵
	power (k);
	A = A * B;
	for (int i = 1; i <= n; i++)
	{
    
    
		for (int j = n + 1; j <= n * 2; j++)
			printf ("%lld ", A.aed[i][j]);
		printf ("\n");
	}
}

猜你喜欢

转载自blog.csdn.net/qq_39940018/article/details/111405860