快速幂题解

快速幂凭自己理解去写的代码比较繁杂:

#include<bits/stdc++.h>
using namespace std;
long long kuaisumi(long long a,long long b,long long m)
{
	long long sum=1;
	while(1)
	{
		if(b==1)return a*sum%m;
		else if(b%2)
		{
			sum=sum*a%m;
			a=a*a%m;
			b/=2;
		}
		else 
		{
			a=a*a%m;
			b/=2;
		}
	}
}
int main()
{
	long long a,b,m;
	cin>>a>>b>>m;
	long long p=kuaisumi(a,b,m)%m;
	cout<<p<<endl;
}

所以后面就直接换成快速幂的板子了,观感和写法都会方便很多,有助于代码规整程度:

#include<bits/stdc++.h>
using namespace std;
int quickpow(long long a,long long b,long long m)
{
	int res=1;
	while(b)
	{
		if(b%2)res=res*a%m;
		a=a*a%m;
		b/=2;
	}
	return res;
}
int main()
{
	int a,b,m;
	cin>>a>>b>>m;
	int p=quickpow(a,b,m)%m;
	cout<<p<<endl;
}

麦森数

通过快速幂结合高精度乘法

但是早上的代码过了放到下午就过不了了,交了两遍一模一样的代码结果却报了两个错误,有点懵逼,目前还没找到原因,先附上早上AC的代码

#include<bits/stdc++.h>
using namespace std;
int la,lb;
const int N=600;
int Times(int res[],int A[])
{
	int C[N];
	memset(C,0,sizeof(C));
	for(int i=1;i<=500;i++)
	{
		for(int j=1;j<=500;j++)
		{
			if(i+j-1>500)continue;
			C[i+j-1]=C[i+j-1]+A[i]*res[j];
			C[i+j]+=C[i+j-1]/10;
			C[i+j-1]%=10;
		}
	}
	for(int i=1;i<=500;i++)res[i]=C[i];
}
int quickpow(int A[],int p)
{
	int res[N];
	memset(res,0,sizeof(res));
	res[1]=1;
	while(p)
	{
		if(p%2)Times(res,A);
		Times(A,A);
		p/=2;
	}
	res[1]--;
	int t=1;
	while(res[t]<0)
	{
		res[t+1]--;
		res[t]+=10;
		t++;
	}
	for(int i=500;i>=1;i--)
	{
		cout<<res[i];
	}
}
int main()
{
	int p,m;
	cin>>p;
	int A[N];
	memset(A,0,sizeof(A));
	A[1]=2;
	printf("%d\n",(int)(log10(2)*p+1));
	quickpow(A,p);
}

矩阵快速幂也是快速幂的一种,只不过乘法部分是矩阵乘法,这里我就直接手写一段矩阵乘法的子程序就可以了

但是不知道为什么在定义Mod前面不加const导致超时,洛谷上面跑了一下要3s,加了const的话就是0.9s左右,不是很懂为什么,不过之后遇到这种全局变量不变的定义就直接加const好了,视频给的板子是重载乘号来实现的,代码更简洁。

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int Mod=1e9+7,N=105;
int n,k;
void Times(int res[][105],int a[][105])
{
	int c[N][N];
	memset(c,0,sizeof(c));
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			for(int p=1;p<=n;p++)
			{
				c[i][j]=(c[i][j]%Mod+res[i][p]*a[p][j]%Mod)%Mod;
			}
		}
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)res[i][j]=c[i][j];
	}
}
void quickpow(int a[][105])
{
	int res[105][105];
	memset(res,0,sizeof(res));
	for(int i=1;i<=n;i++)res[i][i]=1;
	while(k)
	{
		if(k%2)Times(res,a);
		Times(a,a);
		k/=2;
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			cout<<res[i][j];
			cout<<" ";
		}
		cout<<endl;
	}
}
signed main()
{
	int a[105][105];
	cin>>n>>k;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)cin>>a[i][j]; 
	}
	quickpow(a);
}
#include<bits/stdc++.h>
using namespace std;
const long long Mod=1e9+7,N=105;
int n;
long long k;
struct matric
{
	long long c[105][105];
	matric()
	{
		memset(c,0,sizeof c);
	}
}a,res;
matric operator*(matric &x,matric &y)
{
	matric t;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			for(int p=1;p<=n;p++)
			{
				t.c[i][j]=(t.c[i][j]%Mod+(x.c[i][p]*y.c[p][j])%Mod)%Mod;
			}
		}
	}
	return t;
}
void quickpow(long long k)
{
	for(int i=1;i<=n;i++)res.c[i][i]=1;
	while(k)
	{
		if(k&1)res=res*a;
		a=a*a;
		k>>=1;
	}
}
signed main()
{
	cin>>n>>k;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)cin>>a.c[i][j]; 
	}
	quickpow(k);
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			cout<<res.c[i][j]%Mod<<" ";
		}
		if(i!=n)cout<<endl;
	}
}

裴波那契数列的第n项以前写过,但是忘了,看到用矩阵实现就想起来的,本质上就是用矩阵的方法来通过矩阵快速幂从而直接得到第N项的值,之后那个题也是通过矩阵快速幂去实现的,只是后面那题是Fn=Fn-1+Fn-3

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
//#define int long long
#define ios ios::sync_with_stdio(false); cin.tie(0);cout.tie(0)
const int N = 1e5+5;
int n, mod;
struct Matrix{
    int a[3][3];
    Matrix() { memset(a, 0, sizeof(a)) ;}
    Matrix operator* (const Matrix &b) const{
        Matrix res;
        for(int i = 1; i <= 2; i++){
            for(int j = 1; j <= 2; j++){
                for(int k = 1; k <= 2; k++){
                    res.a[i][j] = (res.a[i][j] + 1ll*a[i][k] * b.a[k][j] % mod ) % mod;
                }
            }
        }
        return res;
    }
}base, ans;
void init(){
    base.a[1][1] = base.a[1][2] = base.a[2][1] = 1;
    ans.a[1][1] = ans.a[1][2] = 1;
}
void qpow(int b){
    Matrix res;
    res.a[1][1] = res.a[2][2] = 1;
    while(b){
        if(b & 1) res = res * base;
        base = base * base;
        b >>= 1;
    }
    ans = ans * res;
    cout << ans.a[1][1] << endl;

}

void solve(){
    cin >> n >> mod;
    init();
    if(n < 3){
        cout << 1 << endl;
        return ;
    }
    qpow(n - 2);
}

signed main(){
    ios; int _;
    _ = 1; //cin >> _;
    while(_--){
        solve();
    }
    return 0;
}
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int Mod=1e9+7;
void Times(int a[][5],int b[][5])
{
	int c[5][5];
	memset(c,0,sizeof(c));
	for(int i=1;i<=3;i++)
		for(int j=1;j<=3;j++)
			for(int p=1;p<=3;p++)c[i][j]=(c[i][j]+a[i][p]*b[p][j]%Mod)%Mod;
	for(int i=1;i<=3;i++)
		for(int j=1;j<=3;j++)a[i][j]=c[i][j];
}
void mul(int n)
{
	int a[5][5]={{},{0,0,0,1},{0,1,0,0},{0,0,1,1}},res[5][5]={{},{0,1,0,0},{0,0,1,0},{0,0,0,1}};
	while(n)
	{
		if(n%2)Times(res,a);
		Times(a,a);
		n/=2;
	}
	cout<<(res[1][3]+res[2][3]+res[3][3])%Mod<<endl;
}
signed main()
{
	int t;
	cin>>t;
	while(t--)
	{
		int n;
		cin>>n;
		if(n<=3)
		{
			cout<<1<<endl;
			continue;
		}
		mul(n-3);
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值