快速幂
一、快速幂
思路:反复平方法
将k拆分成若干个2的n次方相加的形式,并用预处理好的a2的0次方~2的logk次方进行组合相乘得到ak。
第一步:预处理出 a^2的0次方 ~2的logk次方^ mod P的结果,一共 logk 个。
预处理时,a2的k次方 = a2的(k-1)次方* a2的(k-1)次方 = a2的(k-1)次方的平方
第二步:将ak组合出来
int qmi(int a, int k, int p){
int res = 1;
while(k){
if(k & 1) res = (ll)res * a % p;//如果k的二进制位有1那么就乘上当前的a
k >>= 1;//k向右移一位
a = (ll)a * a % p;//将a变成下一步的a
}
return res;
}
完整代码
#include<bits/stdc++.h>
using namespace std;
int n;
typedef long long ll;
int qmi(int a, int k, int p){
int res = 1;
while(k){
if(k & 1) res = (ll)res * a % p;
k >>= 1;
a = (ll)a * a % p;
}
return res;
}
int main(){
cin >> n;
while(n --){
int a, k, p;
cin >> a >> k >> p;
cout << qmi(a, k, p) << endl;
}
return 0;
}
二、快速幂求逆元
思路
……
这里输入的a是题目定义里面的b,p是定义里的m。
所以求a的逆元的话,只需满足 a,p互质,
然后根据公式 算出 ap-2 mod p 的值就好。
.
……
总的来说,直接求 (a/b)%m可能会出错,于是想办法用一个x来代替b-1的作用,使得(a *x)mod p同余于(a/b)%m
……辅助说明
2、来自 @Dunyb 的文章 《逆元》
完整代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int qmi(int a, int k, int p){
int res = 1;
while(k){
if(k & 1) res = (ll)res * a % p;
k >>= 1;
a = (ll) a * a % p;
}
return res;
}
int main(){
int n;
cin >> n;
while(n --){
int a, p;
cin >> a >> p;
if(a % p) {//p已经是质数了,那么如果a还不能整除p,就说明它们互质
int res = qmi(a, p - 2, p);
cout << res << endl;
}
else cout << "impossible" << endl;
}
return 0;
}