Matrix Power Series【矩阵乘法】

Time Limit: 3000MS Memory Limit: 131072K
Total Submissions: 35006 Accepted: 14029


Description

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


题目翻译

给定一个 n × n n×n n×n矩阵a和一个正整数k,求和 S = a + A 2 + A 3 + … + A k S=a+A2+A3+…+Ak S=a+A2+A3++Ak

输入
只包含一个测试用例。输入的第一行包含三个正整数 n ( n ≤ 30 ) 、 k ( k ≤ 1 0 9 ) 和 m ( m < 1 0 4 ) n(n≤30)、k(k≤10^9)和m(m<10^4) nn30kk109mm<104。然后跟随n行,每行包含 32768 32768 32768以下的n个非负整数,按照行的主要顺序给出A的元素。

输出
以与A相同的方式输出S模m的元素。


解题思路

矩阵乘法

考虑 1 × 2 1×2 1×2的矩阵 【 A n − 1 , S [ n − 2 ] 】 【A^n-1,S[n-2]】 An1,S[n2],注意此1×2矩阵的2个元素都是r阶方阵!我们希望通过乘以某2×2的矩阵M,得到1×2的矩阵 【 A n , S [ n − 1 ] 】 = 【 A n − 1 ∗ A , A n − 1 + S [ n − 2 ] 】 【A^n,S[n-1]】=【A^n-1*A, An-1+S[n-2]】 An,S[n1]An1A,An1+S[n2]
容易构造出此矩阵M为:
在这里插入图片描述
其中4个元素均为r阶方阵,O表示r阶全0矩阵,E表示单位矩阵(主对角线上为1,其它全为0)。
问题解决。我们的复杂度是: ( 2 r ) 3 ∗ l o g n (2r)3*logn (2r)3logn

其实,这个矩阵就是那个流行方法中用到的,这里我们用前面几个问题的思想很容易构造出了这个 2 r ∗ 2 r 2r*2r 2r2r的矩阵。因此:此思想高效、一般、统一、和谐!


代码

#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
long long nn,k,mm;
struct c{
	long long n,m;
	long long a[100][100];
}A,B,CC;
c operator *(c A,c B){
	c C;
	C.n=A.n,C.m=B.m;
	for(int i=1;i<=C.n;i++)
		for(int j=1;j<=C.m;j++)
			C.a[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.a[i][j]=(C.a[i][j]+(A.a[i][k]*B.a[k][j])%mm)%mm;
	}	
	return C;
}
void poww(long long x){
	if(x==1)
	{
		B=A;
		return; 
	}
	poww(x>>1);
	B=B*B;
	if(x&1)
		B=B*A;
	
}
int main(){
	scanf("%lld%lld%lld",&nn,&k,&mm);
	CC.n=nn,CC.m=2*nn;
	A.n=2*nn,A.m=2*nn;
	for(int i=1;i<=nn;i++)
		for(int j=1;j<=nn;j++)
		{
			scanf("%lld",&CC.a[i][j]);
			CC.a[i][j]=CC.a[i][j]%mm;
			A.a[i][j]=CC.a[i][j];
		}	
	for(int i=1;i<=nn;i++)
		for(int j=nn+1;j<=2*nn;j++)
			if(j-nn==i)
				A.a[i][j]=1;	
	for(int i=nn+1;i<=2*nn;i++)
		for(int j=nn+1;j<=2*nn;j++)
			if(j==i)
				A.a[i][j]=1;
	poww(k);
	CC=CC*B;
	
	for(int i=1;i<=nn;i++)
	{
		for(int j=nn+1;j<=2*nn;j++)
			printf("%lld ",CC.a[i][j]);
		printf("\n");
	}		
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值