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

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

快速幂

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

在这里插入图片描述

递归实现

递归的思想就是利用二分法。它基于如下事实:
(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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值