快速乘/幂详解
快速乘/幂适用范围
快速乘算法适用于计算a*b、a%b、a mod b的结果,主要目的是将乘法换为加法,防止结果过大溢出;快速幂算法适用于计算a^b、a%b、a mod b的结果,降低时间复杂度。
快速乘/幂实现原理
基于按照二进制位一步一步乘来避免重复的操作,利用前面的中间结果,从而实现快速的目的。
对于乘数b,必定可以拆成二进制,有些位为0有些为1。根据乘法分配律:
a
∗
b
=
a
∗
(
b
1
+
b
2
+
b
3...
)
a*b = a*(b1+b2+b3...)
a∗b=a∗(b1+b2+b3...),例如,
a
∗
53
=
a
∗
110101
(
二
进
制
)
=
a
∗
(
100000
+
10000
+
100
+
1
)
a*53 = a*110101(二进制) = a*(100000+10000+100+1)
a∗53=a∗110101(二进制)=a∗(100000+10000+100+1),可以维护一个
a
n
s
=
0
ans=0
ans=0用于保存结果,每一位让
a
∗
=
2
a*=2
a∗=2,再根据b对应位是否为1,如果是就加上当前的a,即可完成快速运算,假定a=5,则具体计算流程如下图所示:
即可计算出
5
∗
53
=
265
5*53=265
5∗53=265。
类似的,快速幂也是一样的过程,只不过每次a更新不是
∗
2
*2
∗2,而是
a
=
a
∗
a
a=a*a
a=a∗a,
a
n
s
+
ans+
ans+变为
a
n
s
∗
ans*
ans∗。
C++实现
// 一、快速幂
// 1、求a^b
int pow(int a, int k) {
int ans = 1;
while(k) {
// 判断奇偶只用判断最后一位,比取模快
if(k & 1) ans *= a;
a *= a;
k >>= 1;
}
return ans;
}
// 2、求a^b%p
int pow_mod(int a, int k,int mod) {
int ans = 1 % mod;
while(k) {
if(k & 1) ans = (long long) ans * a % mod; //防止在对P取模前溢出
a = (long long) a * a % mod;
k >>= 1;
}
return ans;
}
// 二、快速乘
// 1、普通快速乘
long long quickMul(long long a, long long b, long long mod) {
long long ans = 0;
while(b) {
if(b & 1) ans = (ans + a) % mod;
a = (a+a) % mod; // 计算机中加法比乘法快
b >>= 1;
}
return ans;
}
// 2、高效快速乘
long long quickMul(long long a, long long b, long long mod) {
a %= mod;
b %= mod;
long long ans = 0;
while(b) {
if(b & 1) {
ans += a;
if(ans >= mod) ans -= mod;
}
b >>= 1;
a <<= 1;
if(a >= mod) a -= mod;
}
return ans;
}
// 3、使用long double优化
long long quickMul(long long a, long long b, long long mod) {
a %= mod;
b %= mod;
long long c = (long double) a * b / mod;
long long ans = a * b - c * mod;
if(ans < 0)
ans += mod;
else if(ans >= mod)
ans -= mod;
return ans;
}
Python、Java实现后续补上!