快速幂+矩阵快速幂模板

快速幂

运用位运算

强大的位运算把我搞得蒙蒙的
理解了之后我表示很喜欢!!!

代码

int power(int n,int g){
	int ans=1;
	while(n){
		if(n&1) ans*=g;
		g*=g;
		n>>=1;
	}
	return ans;
}

分析

一点理解…
如果不懂位运算就去搜搜叭 好多大神写的很棒
在这里插入图片描述

不过因为快速幂很容易就溢出,int用long long会好一丢丢(因为就算改了也很容易溢出hhh)
可能题目会有说用mod叭…

矩阵快速幂

(用于矩阵乘法计算)
一般可用于优化dp(后面会给几道题目)

题目

来道模板题
在这里插入图片描述

分析

(前置知识:矩阵乘法,线代中有学)
由于矩阵乘法直接计算需要 O ( n 3 ) O(n^3) O(n3)一旦数据过大易TLE,所以我们可以通过快速幂的思想来优化相同矩阵的计算(实际上矩阵快速幂=矩阵乘法+快速幂)

代码

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const ll mod=1e9+7;

ll n;
struct sz{
	ll a[110][110];
}b,c;

sz mul(sz x,sz y){//矩阵X与矩阵Y相乘
	sz c;
	for(ll i=1;i<=n;i++)//初始化
	for(ll j=1;j<=n;j++) c.a[i][j]=0;
	for(ll i=1;i<=n;i++){
		for(ll j=1;j<=n;j++){
			for(ll k=1;k<=n;k++){
				c.a[i][j]=(c.a[i][j]+(x.a[i][k]*y.a[k][j])%mod)%mod;
			}
		}
	}
	return c;
}

sz qpower(ll k,ll mod){//实际上就是快速幂的模板
	sz ans;
	for(ll i=1;i<=n;i++) ans.a[i][i]=1;//单位矩阵,相当于快速幂中ans=1的操作,单位矩阵*A=A
	while(k){
		if(k&1){
			ans=mul(ans,b);
		}
		k>>=1;
		b=mul(b,b);
	}
	return ans;
} 

int main(){
	ios::sync_with_stdio(0); cin.tie(0);
	ll k;
	cin>>n>>k;
	for(ll i=1;i<=n;i++){
		for(ll j=1;j<=n;j++){
			cin>>b.a[i][j];
		}
	}
	c=qpower(k,mod);
	for(ll i=1;i<=n;i++){
		for(ll j=1;j<=n;j++){
			cout<<c.a[i][j]<<' ';
		}cout<<endl;
	} 
	return 0; 
}
拓一、、:
sz mul(sz x,sz y){//矩阵X与矩阵Y相乘
	sz c;
	for(ll i=1;i<=n;i++)//初始化
	for(ll j=1;j<=n;j++) c.a[i][j]=0;
	for(ll i=1;i<=n;i++){
		for(ll j=1;j<=n;j++){
			for(ll k=1;k<=n;k++){
				c.a[i][j]=(c.a[i][j]+(x.a[i][k]*y.a[k][j])%mod)%mod;
			}
		}
	}
	return c;
}

这里可以来个小优化,变为:

sz mul(sz x,sz y){//矩阵X与矩阵Y相乘
	sz c;
	for(ll i=1;i<=n;i++)//初始化
	for(ll j=1;j<=n;j++) c.a[i][j]=0;
	for(ll i=1;i<=n;i++){
		for(ll k=1;k<=n;k++){
			for(ll j=1;j<=n;j++){
				c.a[i][j]=(c.a[i][j]+(x.a[i][k]*y.a[k][j])%mod)%mod;
			}
		}
	}
	return c;
}

k、j位置改变,可优化时间
从:
在这里插入图片描述

到:
在这里插入图片描述

x.a[i][k]*y.a[k][j]

原因:在y.a[k][j]中,时遍历j的位置比遍历k的位置快;
可以这样理解:
在这里插入图片描述
主要还是因为计算机遍历过程中的长度

矩阵快速幂的写法还有operator,可了解一下~

const int mod=2017;
const int N=110;
int n;
struct jz{
	int n,m,a[N][N];
	jz(){//初始化
		n=m=0;
		memset(a,0,sizeof a);
	}
};
jz operator * (const jz &x,const jz &y){
	jz c;
	c.n =x.n ;c.m =y.m ;
	for(int i=0;i<=c.n ;i++)
		for(int k=0;k<=x.m ;k++)
			for(int j=0;j<=c.m ;j++){
				c.a[i][j]=(c.a[i][j]+x.a[i][k]*y.a[k][j]%mod)%mod;
			}
	return c;
}

jz qpower(jz a,int b){
	jz ans;
	ans.m =ans.n =n;
	for(int i=0;i<=n;i++)ans.a[i][i]=1;
	while(b){
		if(b&1)ans=ans*a;
		a=a*a;
		b>>=1;
	}
	return ans;
}

调用:(x为矩阵,t为幂,即 x t x^t xt

jz res=qpower(x,t);

我滴板子:

typedef long long ll;
const int N=待填;
const ll mod=待填;

struct jz{
	ll a[N][N];
	
	void init(int x){//初始化
		memset(a,0,sizeof(a));
		for(int i=0;i<N;i++)//可变单位矩阵
			a[i][i]=x;
		
	}
	
	jz operator * (const jz &b) const {//矩阵乘法
		jz res;
		res.init(0);
		for(int i=0;i<N;i++)
			for(int k=0;k<N;k++)
				for(int j=0;j<N;j++)
					res.a[i][j]=(res.a[i][j]+a[i][k]*b.a[k][j]%mod)%mod;
		return res;
	}
	
	jz operator + (const jz &b) const {//矩阵加法
		jz res;
		res.init(0);
		for(int i=0;i<N;i++)
			for(int j=0;j<N;j++)
				res.a[i][j]=(res.a[i][j]+(a[i][j]+b.a[i][j])%mod)%mod;
		return res;
	}
	
}ini,res;


jz qpower(jz x,ll k){//矩阵快速幂
	jz res;
	res.init(1);
	while(k){
		if(k&1)
			res=res*x;
		x=x*x;
		k>>=1;
		
	}
	return res;
}

矩阵快速幂练习:
P5789 [TJOI2017]可乐题解
简单计数题解
Matrix Power Series题解

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值