【洛谷P3390】(模板)矩阵快速幂

题目链接

(模板)矩阵快速幂

题目背景

矩阵快速幂

题目描述

给定(n imes n)的矩阵(A),求(A^k)

输入格式

第一行两个整数(n,k)接下来(n)行,每行(n)个整数,第(i)行的第(j)的数表示(A_{i,j})

输出格式

输出(A^k)(n)行,每行(n)个数,第(i)行第(j)个数表示((A^k)_{i,j}),每个元素对(10^9+7)取模。

样例输入

2 1
1 1
1 1

样例输出

1 1
1 1

说明/提示

【数据范围】
对于(100\%)的数据:(1le n le 100)(0 le k le 10^{12}),(|A_{i,j}| le 1000)

题解

明显这是一道矩阵快速幂的板题,下面先介绍一下矩阵快速幂吧。
矩阵快速幂就是把矩阵乘法和快速幂结合一下。
对于矩阵的计算,这里就讲一下矩阵乘法,其他运算就不赘述了。
对于两个矩阵(A)(B),它们的行数和列数分别为(ax,ay,bx,by)
要能进行(A imes B),需要满足(ay=bx)
(A imes B)的结果是矩阵(C)(C)的行数和列数分别为(ax,by)(C_{j,i}=sum^{ay}_{k=1}A_{j,k}*B_{k,i})
也就是说(C)的第(i)行第(j)列等于(A)的第(i)行和(B)的第(j)列,各个对应的数的乘积的和。
关于快速幂的话想必大家都会了,那么我们只要定义一个(struct)来存储矩阵,然后重载一下运算符,就和普通的快速幂没有区别了。
如果不会重载运算符的话也可以写一个函数。
注意:因为中间有乘法,所以要开(long long),还要记得取模,刚开始打的时候取模少了一个(0),调了半天o(╥﹏╥)o
上代码:

#include<bits/stdc++.h>
#define mod 1000000007
using namespace std;
int n;
long long k;
struct aa{
	long long a[109][109];
	aa operator * (aa x){
		aa uans;
		for(int j=1;j<=n;j++)
			for(int i=1;i<=n;i++){
				uans.a[j][i]=0;
				for(int p=1;p<=n;p++)
					uans.a[j][i]=(uans.a[j][i]+a[j][p]*x.a[p][i]%mod)%mod;
			}
		return uans;
	}
};
aa ksm(aa x,long long p){
	aa uans;
	for(int j=1;j<=n;j++)
		for(int i=1;i<=n;i++)
			if(i==j) uans.a[j][i]=1;
			else uans.a[j][i]=0;
	while(p){
		if(p&1) uans=uans*x;
		x=x*x;
		p>>=1;
	}
	return uans;
}
int main(){
	scanf("%d%lld",&n,&k);
	aa a;
	for(int j=1;j<=n;j++)
		for(int i=1;i<=n;i++)
			scanf("%lld",&a.a[j][i]);
	aa ans=ksm(a,k);
	for(int j=1;j<=n;j++){
		for(int i=1;i<=n;i++)
			printf("%lld ",ans.a[j][i]);
		puts("");
	}
	return 0;
}
原文地址:https://www.cnblogs.com/linjiale/p/13068408.html