快速冪(二分法,位運算)

題目鏈接: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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章