快速幂
运用位运算
强大的位运算把我搞得蒙蒙的
理解了之后我表示很喜欢!!!
代码
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:题解