快速幂:
中自带的 函数在调用时需要一系列类型转换;数值并不是严格精确,存在误差;执行效率低。最好不要用。
然而自己用累乘法写的朴素函数执行效率低下,时间复杂度 。
算法 () , 是一种高效的快速幂算法,时间复杂度 。
原理:
求 时,朴素方法需要累乘 n 次。假如 n 是 2 的指数型,可以表示为 ,所以可以转化成:
就压缩到了 k 次平方运算。
可以把这个方法推广到任意 n , 把 n 转化为二进制的形式:
那么
所以只需要求到最高位的 便可。
举个例子,求 , 37 的二进制为 100101 ,每个 1 的权依次是 32 、4、1 ,所以就有:
代码:
ll mod_pow(ll x, ll n, ll mod) { //挑战
ll res = 1;
while (n > 0) {
if (n & 1) res = res * x % mod;
x = x * x % mod;
n >>= 1;
}
return res;
}
还有一种递归的实现:
ll mod_pow(ll x, ll n, ll mod) {
if (n == 0) return 1;
ll res = mod_pow(x * x % mod, n / 2, mod);
if (n & 1) res = res * x % mod;
return res;
}
大数乘法取模:
有一点需要注意,就是在计算 x * x % mod 和 res * x % mod 时,由于 x 与 res 都会很大,直接相乘可能溢出 long long 的数据范围,此时就需要用大数乘法取模的方法。
代码:
typedef long long ll;
ll mod_mult(ll a, ll b, ll mod) {
a %= mod;
b %= mod;
ll ans = 0;
while (b > 0) {
if (b & 1) {
ans += a;
if (ans >= mod)
ans -= mod;
}
a <<= 1;
if (a >= mod) a = a - mod;
b >>= 1;
}
return ans;
}