【PKU 3233】Matrix Power Series【矩阵乘法の变式】

T i m e Time Time L i m i t : Limit: Limit: 3000 M S 3000MS 3000MS
M e m o r y Memory Memory L i m i t : Limit: Limit: 131072 K 131072K 131072K

Description

l i n k link link
Given a n × n n × n n×n matrix A A A and a positive integer k k k, find the sum S = A + A 2 + A 3 + … + A k S = A + A^2 + A^3 + … + A^k 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

分析:

直接计算会超时 考虑矩阵 [ A i − 1 , S i − 2 ] [A^{i-1},S_{i-2}] [Ai1,Si2]
[ A i , S i − 1 ] = [ A i − 1 , S i − 2 ] ∗ F [A^i,S_{i-1}]=[A^{i-1},S_{i-2}]*F [Ai,Si1]=[Ai1,Si2]F
F F F变换矩阵 那么可得 F F F为:
A , E A,E A,E

O , E O,E O,E
其中 E E E表示单位矩阵 O O O为全是 0 0 0的矩阵
注意初始矩阵构造要展开构造
S S S就在初始矩阵 [ 1 ] [ 2 ] [1][2] [1][2]

CODE:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
ll n,mod,k;
struct matrix{
	ll n,m;
	ll F[101][101];
}A,B,C;
matrix operator *(matrix a,matrix b)
{
	matrix c;
	c.n=a.n;c.m=a.m;
	for(int i=1;i<=c.n;i++)
		for(int j=1;j<=c.m;j++)
			c.F[i][j]=0;
	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.F[i][j]=(c.F[i][j]+a.F[i][k]*b.F[k][j]%mod)%mod;  //矩阵乘法
	return c;
}
void ksm(ll x)
{
	if(x==1){
		B=A;
		return;
	}
	ksm(x/2);
	B=B*B;
	if(x&1) B=B*A;
}
int main(){
	scanf("%lld%lld%lld",&n,&k,&mod);
	C.n=n;C.m=2*n;A.n=n*2;A.m=n*2;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			scanf("%lld",&C.F[i][j]);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			A.F[i][j]=C.F[i][j];
	for(int i=1;i<=n;i++)
		for(int j=n+1;j<=n+n;j++)
			if(i+n==j)  //赋单位矩阵
				A.F[i][j]=1;  //相当于初始矩阵[1][2]的初值
	for(int i=n+1;i<=n+n;i++)
		for(int j=n+1;j<=n+n;j++)
			if(i==j)  //同单位矩阵
				A.F[i][j]=1;  //初始矩阵[2][2]的初值
	ksm(k);
	C=C*B;
	for(int i=1;i<=n;i++)
	{
		for(int j=n+1;j<=n+n;j++)
			printf("%lld ",C.F[i][j]);  //输出[1][2]
		printf("\n");
	}
	
	return 0;
} 
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值