快速冪及其取餘
阿新 • • 發佈:2019-02-13
快速冪
快速冪的作用:快速計算底數的n次冪。
時間複雜度為:O(log₂N) (樸素方法為O(N)
原理
以下以求a的b次方來介紹
把b轉換成二進位制數
該二進位制數第i位的權為
例:
11的二進位制是1011
因此,我們將轉化為算
程式碼
遞迴版
int powf(int a, int b){
if(b == 1)
return a;
int t = powf(a, b/2);
return (b%2 == 0 ? 1 : a)*t*t;
}
迴圈版
int pow0(int a, int b){
int r = 1, base = a;
while(b != 0){
if(b%2)
r *= base;
base *= base;
b /= 2;
}
return r;
}
//常規求冪
int pow1(int a, int b){
int r = 1;
while(b--)
r *= a;
return r;
}
//快速求冪(位運算)
int pow2(int a, int b){
if(b == 0)
return 1;
else {
while((b&1) == 0){
b >>= 1;
a *= a;
}
}
int r = a;
b >>= 1;
while(b != 0){
a *= a;
if(b & 1)
r *= a;
b >>= 1 ;
}
return r;
}
//快速求冪(位運算,簡潔版)
int pow3(int a, int b){
int r = 1, base = a;
while(b){
if(b & 1)
r *= base;
base *= base;
b >>= 1;
}
return r;
}
測試
#include <stdio.h>
//a^b
int powf(int a, int b){
if(b == 1)
return a;
int t = powf(a, b/2);
return (b%2 == 0 ? 1 : a)*t*t;
}
int pow0(int a, int b){
int r = 1, base = a;
while(b != 0){
if(b%2)
r *= base;
base *= base;
b /= 2;
}
return r;
}
//常規求冪
int pow1(int a, int b){
int r = 1;
while(b--)
r *= a;
return r;
}
//快速求冪(位運算)
int pow2(int a, int b){
if(b == 0)
return 1;
else {
while((b&1) == 0){
b >>= 1;
a *= a;
}
}
int r = a;
b >>= 1;
while(b != 0){
a *= a;
if(b & 1)
r *= a;
b >>= 1;
}
return r;
}
//快速求冪(位運算,簡潔版)
int pow3(int a, int b){
int r = 1, base = a;
while(b){
if(b & 1)
r *= base;
base *= base;
b >>= 1;
}
return r;
}
int main(void)
{
int a, b;
scanf("%d%d", &a, &b);
printf("遞迴版:\n");
printf("%d^%d = %d\n\n", a, b, powf(a, b));
printf("迴圈版:\n");
printf("%d^%d = %d\n\n", a, b, pow0(a, b));
printf("常規求冪:\n");
printf("%d^%d = %d\n\n", a, b, pow1(a, b));
printf("位運算1:\n");
printf("%d^%d = %d\n\n", a, b, pow2(a, b));
printf("位運算2:\n");
printf("%d^%d = %d\n\n", a, b, pow3(a, b));
return 0;
}
快速冪取餘
首先要證明一個公式:a*b%m = a%mb%m%m
a*b%m = %m = a%mb%m%m
進而
%m = a%m%m = a%ma%m%m = { a%ma%m%m }%m
程式碼
#include <stdio.h>
long long powMod(long long a, long long b, long long mod)
{
long long ans = 1;
a %= mod;
while(b){
if(b&1)
ans = ans*a%mod;
a = a*a%mod;
b >>= 1;
}
return ans;
}
int main(void)
{
int a, b, mod;
scanf("%d%d%d", &a, &b, &mod);
printf("%d^%d%%%d = %lld\n\n", a, b, mod, powMod(a, b, mod));
return 0;
}