1.快速幂
只写关键点:
以5的35次方为例,base = 5, power = 35;
power的二进制表示为 100011
那么
因为
所以我们每次移动都用位运算算一位就可以,然后更新ans, 更新base。
代码如下:
int qmi(int base, int power){
int res = 1;
while (power){
if(power & 1){
res *= base;
}
base = base * base;
power >>= 1;
}
return res;
}
2.快速幂求乘法逆元
乘法逆元的定义如下:
为什么是b的乘法逆元呢:
a / b ≡ a * x (mod n)
两边同乘b可得 a ≡ a * b * x (mod n)
即 1 ≡ b * x (mod n)
同 b * x ≡ 1 (mod n)
由费马小定理可知,当n为质数时
b ^ (n - 1) ≡ 1 (mod n)
拆一个b出来可得 b * b ^ (n - 2) ≡ 1 (mod n)
故当n为质数时,b的乘法逆元 x = b ^ (n - 2)
求b ^ (n - 2) (mod n)可以用我们之前学过的快速幂算法来做
特别注意的是,如果要求乘法逆元,首先要判断是不是互质,我们可以使用gcd来判断。
但是由于已知一个数是质数,质数只与它的倍数不互质。所以我们直接使用(a % p) == 0即可。
代码如下:
#include <bits/stdc++.h>
using namespace std;
int qmi(int base, int power, int mod) {
int res = 1;
while (power) {
if (power & 1) {
res = res * base % mod;
}
base = base * base % mod;
power >>= 1;
}
return res;
}
int main() {
int n;
cin >> n;
while (n--) {
int a, p;
cin >> a >> p;
if (a % p == 0) cout << "impossible" << endl;
else cout << qmi(a, p - 2, p) << endl;
}
return 0;
}