快速冪的用途
顧名思義,快速冪就是很快速的冪運算,試想當你面對一個問題:求abab的時候,你的第一反應是開long long然后用for循環一點一點求。那么你就已經會了冪運算的O(b)算法。按常理來講,這樣的算法已經夠用了,但是遇到一些卡時間的題目的時候還是會T,於是快速冪應運而生。簡單地說,快速冪就是一種復雜度為O(logb)的求冪運算的算法。
快速冪的實現原理
對於ab,快速冪的時間復雜度是O(logb)的。一個整數可以被拆分成若干個2k的和。可以把b二進制分解,成為若干個2k的和,也就是將b轉換為2進制按權相加式。
b = x020 + x121 + x222 + … + xn-12n-1。
再由ab = a^b = a^(x0*20 + x1*21 + x2*22 + … + xn-1*2n-1),可以減少乘法操作的次數,先是基數21~2n,先進行了n次乘法,再由有效位(b的二進制形式中,數碼為1的位)的位數m,額外進行m-1次的計算,則總共計算了n+m-1次,即得到計算次數不超過log2c + m – 1次。從原來的乘n次變為現在的最多乘2log2n次,因此,時間復雜度由原來的O(b)減小為現在的O(log2b)。
舉個例子:
求解問題: 342。
第一步,將42二進制拆分:(42)10=(101010)2=1×25+0×24+⋯+0×20
那么, 342就變成了:342=31×32+0×16+1×8+0×4+1×2+0×1 =332*38*32
快速冪的迭代寫法
int qpow(int a,int b)
{
int ret=1;
while(b>0)
{
if(b&1)
ret*=a;
a*=a;
b>>=1;
}
}
return ret;
}
通常,由於int類型以及long long類型的數值范圍限制,通常遇到的OJ題目需要對運算結果取模:
快速冪取模
(a*b)%m = ((a%m)*(b%m))%m;
其實快速冪取模也是用到這個
那么根據上面的定理可以推導出另一個定理:
(ab) mod c = (a * a * a........)%c = ((a%c)*(a%c)*(a%c)*.........)%c = (a%c)b %c;
這就是快速冪取模
代碼如下:
int pow_mod(int a ,int b)
{
int ans = 1 ;
int base = a % c;
while(b>0)
{
if(b&1!=0)
ans = (ans *base)%c;
}
base = (base*base)%c;
b >>= 1;
return ans;
}
快速冪的遞歸代碼實現
在求解ab的時候
1)當b是奇數時,那么有 ab = a * ab
2)當b是偶數時,那么有 ab = a(b/2) * a(b/2)
這個東西可以用遞歸來實現。代碼如下:
int qpow(int a,int b)
{
if(!b)
return 1;
else if(b&1)
return a*qpow(a,b-1);
else
{
int t=qpow(a,b>>1);
return t*t;
}
}