快速幂(二分法,位运算)

题目链接:https://www.luogu.com.cn/problem/P1226
在这里插入图片描述
对于这个问题,当然可以将p个b相乘,但是p的上限是231,而算法的时间复杂度为O§,承受不了这么大的规模。

快速幂

想弄清本题算法,需要先了解取模(求余)运算的一些性质,比如:

在这里插入图片描述

递归实现

递归的思想就是利用二分法。它基于如下事实:
(1)如果p是奇数,那么有bp=b*bp-1
(2)如果p是偶数,那么有bp=bp/2*bp/2
且临界值b0=1.
注意:不能直接写成return binaryPow(b,p/2,k)*binaryPow(b,p/2,k)%k;,这样的话时间复杂度为O(2logp)=O( p )。

#include<bits/stdc++.h>
typedef long long LL;
using namespace std;
LL binaryPow(LL b,LL p,LL k){
	if(p==0) return 1;
	if(p&1==1) return b*binaryPow(b,p-1,k)%k;
	LL mul=binaryPow(b,p/2,k);
	return mul*mul%k;
	//return binaryPow(b,p/2,k)*binaryPow(b,p/2,k)%k;   这么写可不行 
}
int main() {
	LL b,p,k;cin>>b>>p>>k;
	printf("%lld^%lld mod %lld=%lld",b,p,k,binaryPow(b,p,k)%k);  //由于p==0时函数没有对其进行取余操作,所以在这里加一句取余比较保险
	return 0;
}

非递归算法

如果把p写成二进制,那么b就可以写成若干二次幂之和,例如13的二进制是1101,于是13=23+22+20=8+4+1,所以b13=a8*a4*a1.
类似的,对于任意ab,它可以表示为a2k,…,a4,a2,a1中若干项的成绩。其中,若b的二进制i号位位1,则a2i就被选中。

#include<bits/stdc++.h>
typedef long long LL;
using namespace std;
int main() {
	LL b,p,k;cin>>b>>p>>k;
	printf("%lld^%lld mod %lld=",b,p,k);
	LL ans=1;
	while(p>0){
		if(p&1==1){
			ans=ans*b%k;
		}
		b=b*b%k;
		p>>=1;
	}
	printf("%lld",ans%k);
	return 0;
}
发布了136 篇原创文章 · 获赞 12 · 访问量 6083

猜你喜欢

转载自blog.csdn.net/weixin_43590232/article/details/104824533