矩阵快速幂刷题小记

矩阵快速幂模板

传送门: P3390 【模板】矩阵快速幂
Code:

#include<bits/stdc++.h>
using namespace std;
const long long p=1000000007;
inline long long Read(){
	long long dx=0,fh=1;
	char c=getchar();
	while(c>'9'||c<'0'){
		if(c=='-')	fh=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9'){
		dx=dx*10+c-'0';
		c=getchar();
	}
	return dx*fh;
}
long long k,n;
struct Matricx{
	long long a[101][101];
}A;
Matricx mul(Matricx x,Matricx y){
	Matricx z;
	for(long long i=1;i<=n;++i)
		for(long long j=1;j<=n;++j){
			z.a[i][j]=0;
			for(long long u=1;u<=n;++u)
				z.a[i][j]=(z.a[i][j]+(x.a[i][u]*y.a[u][j])%p)%p;
		}
	return z;
}
Matricx quick_pow(Matricx x,long long b){
	Matricx r,base=x;
	for(int i=1;i<=n;++i)	for(int j=1;j<=n;++j)	r.a[i][j]=0;
	for(int i=1;i<=n;++i)	r.a[i][i]=1;
	while(b){
		if(b&1)	r=mul(r,base);
		base=mul(base,base);
		b>>=1;
	}
	return r;
}
int main(){
	n=Read();k=Read();
	for(long long i=1;i<=n;++i)
		for(long long j=1;j<=n;++j)
			A.a[i][j]=Read();
	Matricx B=quick_pow(A,k);
	for(long long i=1;i<=n;++i){
		for(long long j=1;j<=n;++j)
			printf("%lld ",B.a[i][j]);
		putchar('\n');
	}	
	return 0; 
} 

反思与总结:
刚定义的矩阵一定要先全部赋值为0

斐波那契数列

传送门:P1962 斐波那契数列
Code:

#include<bits/stdc++.h>
using namespace std;
const long long p=1000000007;
inline long long Read(){
	long long dx=0,fh=1;
	char c=getchar();
	while(c>'9'||c<'0'){
		if(c=='-')	fh=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9'){
		dx=dx*10+c-'0';
		c=getchar();
	}
	return dx*fh;
}
long long k;
struct Matricx{
	long long a[3][3];
}A;
Matricx mul(Matricx x,Matricx y){
	Matricx z;
	for(long long i=1;i<=2;++i)
		for(long long j=1;j<=2;++j){
			z.a[i][j]=0;
			for(long long u=1;u<=2;++u)
				z.a[i][j]=(z.a[i][j]+(x.a[i][u]*y.a[u][j])%p)%p;
		}
	return z;
}
Matricx quick_pow(Matricx x,long long b){
	Matricx r,base=x;
	for(int i=1;i<=2;++i)	for(int j=1;j<=2;++j)	r.a[i][j]=0;
	for(int i=1;i<=2;++i)	r.a[i][i]=1;
	while(b){
		if(b&1)	r=mul(r,base);
		base=mul(base,base);
		b>>=1;
	}
	return r;
}
int main(){
	k=Read();
	if(k==1||k==2)	printf("1");
	else{
		A.a[1][1]=1,A.a[1][2]=1,A.a[2][1]=1,A.a[2][2]=0;
		Matricx B=quick_pow(A,k-2);
		printf("%lld",(B.a[1][1]+B.a[1][2])%p);
	}
	return 0; 
} 

反思与总结:

  • 要特判n=1或n=2的情况
  • 记得mod p

广义斐波那契数列

传送门: P1349 广义斐波那契数列
题目分析: 简单推一下:
{ f [ n ] = p × f [ n − 1 ] + q × f [ n − 2 ] f [ n − 1 ] = 1 × f [ n − 1 ] + 0 × f [ n − 2 ]    ⟹    [ f [ n ] f [ n − 1 ] ] = [ p q 1 0 ] ∗ [ f [ n − 1 ] f [ n − 2 ] ] \begin{cases} f[n]=p×f[n-1]+q×f[n-2] \\f[n-1]=1×f[n-1]+0×f[n-2] \end{cases}\implies\begin{bmatrix} f[n] \\ f[n-1] \end{bmatrix} =\begin{bmatrix} p & q \\ 1 & 0 \end{bmatrix}*\begin{bmatrix} f[n-1] \\ f[n-2] \end{bmatrix} {f[n]=p×f[n1]+q×f[n2]f[n1]=1×f[n1]+0×f[n2][f[n]f[n1]]=[p1q0][f[n1]f[n2]]
最后别忘了 f [ 1 ] = a 1 f[1]=a1 f[1]=a1, f [ 2 ] = a 2 f[2]=a2 f[2]=a2
Code:

#include<bits/stdc++.h>
using namespace std;
inline long long Read(){
	long long dx=0,fh=1;
	char c=getchar();
	while(c>'9'||c<'0'){
		if(c=='-')	fh=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9'){
		dx=dx*10+c-'0';
		c=getchar();
	}
	return dx*fh;
}
long long n,p,a2,a1,q,m;
struct Matricx{
	long long a[3][3];
}A;
Matricx mul(Matricx x,Matricx y){
	Matricx z;
	for(long long i=1;i<=2;++i)
		for(long long j=1;j<=2;++j){
			z.a[i][j]=0;
			for(long long u=1;u<=2;++u)
				z.a[i][j]=(z.a[i][j]+(x.a[i][u]*y.a[u][j])%m)%m;
		}
	return z;
}
Matricx quick_pow(Matricx x,long long b){
	Matricx r,base=x;
	for(int i=1;i<=2;++i)	for(int j=1;j<=2;++j)	r.a[i][j]=0;
	for(int i=1;i<=2;++i)	r.a[i][i]=1;
	while(b){
		if(b&1)	r=mul(r,base);
		base=mul(base,base);
		b>>=1;
	}
	return r;
}
int main(){
	p=Read();q=Read();a1=Read();a2=Read();n=Read();m=Read();
	if(n==1)	printf("%lld",a1);
	else if(n==2)	printf("%lld",a2);
	else{
		A.a[1][1]=p,A.a[1][2]=q,A.a[2][1]=1,A.a[2][2]=0;
		Matricx B=quick_pow(A,n-2);
		printf("%lld",((B.a[1][1]*a2)%m+(B.a[1][2]*a1)%m)%m);
	}
	return 0; 
} 

【模板】矩阵加速(数列)

传送门:P1939 【模板】矩阵加速(数列)
算法分析:
简单分析一下:
{ f [ n ] = 1 × f [ n − 1 ] + 0 × f [ n − 2 ] + 1 × f [ n − 3 ] f [ n − 1 ] = 1 × f [ n − 1 ] + 0 × f [ n − 2 ] + 0 × f [ n − 3 ] f [ n − 2 ] = 0 × f [ n − 1 ] + 1 × f [ n − 2 ] + 0 × f [ n − 3 ]    ⟹    [ f [ n ] f [ n − 1 ] f [ n − 2 ] ] = [ 1 0 1 1 0 0 0 1 0 ] ∗ [ f [ n − 1 ] f [ n − 2 ] f [ n − 3 ] ]    ⟹    [ f [ n ] f [ n − 1 ] f [ n − 2 ] ] = [ 1 0 1 1 0 0 0 1 0 ] n − 3 × [ f [ 3 ] f [ 2 ] f [ 1 ] ]    ⟹    [ f [ n ] f [ n − 1 ] f [ n − 2 ] ] = [ 1 0 1 1 0 0 0 1 0 ] n − 3 × [ 1 1 1 ] \begin{cases} f[n]=1×f[n-1]+0×f[n-2]+1×f[n-3] \\f[n-1]=1×f[n-1]+0×f[n-2]+0×f[n-3] \\f[n-2]=0×f[n-1]+1×f[n-2]+0×f[n-3] \end{cases} \implies \begin{bmatrix} f[n]\\f[n-1]\\f[n-2] \end{bmatrix} =\begin{bmatrix} 1&0&1 \\ 1&0&0 \\0&1&0 \end{bmatrix} *\begin{bmatrix} f[n-1] \\ f[n-2]\\f[n-3] \end{bmatrix} \implies \begin{bmatrix} f[n]\\f[n-1]\\f[n-2] \end{bmatrix} =\begin{bmatrix} 1&0&1 \\ 1&0&0 \\0&1&0 \end{bmatrix}^{n-3}×\begin{bmatrix}f[3]\\f[2]\\f[1] \end{bmatrix}\implies \begin{bmatrix} f[n]\\f[n-1]\\f[n-2] \end{bmatrix} =\begin{bmatrix} 1&0&1 \\ 1&0&0 \\0&1&0 \end{bmatrix}^{n-3}×\begin{bmatrix}1\\1\\1 \end{bmatrix} f[n]=1×f[n1]+0×f[n2]+1×f[n3]f[n1]=1×f[n1]+0×f[n2]+0×f[n3]f[n2]=0×f[n1]+1×f[n2]+0×f[n3]f[n]f[n1]f[n2]=110001100f[n1]f[n2]f[n3]f[n]f[n1]f[n2]=110001100n3×f[3]f[2]f[1]f[n]f[n1]f[n2]=110001100n3×111
[ 1 0 1 1 0 0 0 1 0 ] \begin{bmatrix} 1&0&1 \\ 1&0&0 \\0&1&0 \end{bmatrix} 110001100 A A A,则 f [ n ] = A [ 1 ] [ 1 ] + A [ 1 ] [ 2 ] + A [ 1 ] [ 3 ] f[n]=A[1][1]+A[1][2]+A[1][3] f[n]=A[1][1]+A[1][2]+A[1][3]
Code:

#include<bits/stdc++.h>
using namespace std;
const long long p=1000000007;
inline long long Read(){
	long long dx=0,fh=1;
	char c=getchar();
	while(c>'9'||c<'0'){
		if(c=='-')	fh=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9'){
		dx=dx*10+c-'0';
		c=getchar();
	}
	return dx*fh;
}
long long k,T;
struct Matricx{
	long long a[4][4];
}A;
Matricx mul(Matricx x,Matricx y){
	Matricx z;
	for(long long i=1;i<=3;++i)
		for(long long j=1;j<=3;++j){
			z.a[i][j]=0;
			for(long long u=1;u<=3;++u)
				z.a[i][j]=(z.a[i][j]+(x.a[i][u]*y.a[u][j])%p)%p;
		}
	return z;
}
Matricx quick_pow(Matricx x,long long b){
	Matricx r,base=x;
	for(int i=1;i<=3;++i)	for(int j=1;j<=3;++j)	r.a[i][j]=0;
	for(int i=1;i<=3;++i)	r.a[i][i]=1;
	while(b){
		if(b&1)	r=mul(r,base);
		base=mul(base,base);
		b>>=1;
	}
	return r;
}
int main(){
	A.a[1][1]=1,A.a[1][2]=0,A.a[1][3]=1;
	A.a[2][1]=1,A.a[2][2]=0,A.a[2][3]=0;
	A.a[3][1]=0,A.a[3][2]=1,A.a[3][3]=0;
	T=Read();
	for(;T;--T){
		k=Read();
		if(k==1||k==2||k==3)	printf("1\n");
		else{
			Matricx B=quick_pow(A,k-3);
			printf("%lld\n",(B.a[1][1]+B.a[1][2]+B.a[1][3])%p);
		}
	}	
	return 0; 
} 
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值