1 介绍
本博客用来记录使用快速幂求解的相关题目。
快速幂,该方法用来快速求解 a k a^k ak取余p的值,时间复杂度为O(logk)。
核心思想:k一定可以表示成
k
=
Σ
j
2
j
k=\Sigma_j2^j
k=Σj2j这样的形式,例如当k=9时,
9
=
2
0
+
2
3
9=2^0+2^3
9=20+23。故,我们先预处理出
a
a
a、
a
2
a^2
a2、
a
4
a^4
a4、
a
8
a^8
a8、
a
16
a^{16}
a16、
a
32
a^{32}
a32、…、
a
2
n
a^{2^n}
a2n等等取余p的值,即
a
%
p
a\ \% \ p
a % p
a
2
%
p
a^2 \ \% \ p
a2 % p
a
4
%
p
a^4 \ \% \ p
a4 % p
a
8
%
p
a^8 \ \% \ p
a8 % p
a
16
%
p
a^{16} \ \% \ p
a16 % p
a
32
%
p
a^{32}\ \% \ p
a32 % p
然后
a
9
=
(
a
%
p
)
⋅
(
a
8
%
p
)
a^9=(a \% p) \cdot (a^8 \% p )
a9=(a%p)⋅(a8%p)
快速幂C++模板如下所示,
//求解a^k%p,时间复杂度为O(logk)
int qmi(int a, int k, int p) {
long long res = 1;
while (k) {
if (k & 1) res = res * a % p;
k >>= 1;
a = (long long)a * a % p; //a * a的结果可能会超过int范围,故加上long long
}
return res;
}
2 训练
题目1:875. 快速幂
C++代码如下,
#include <bits/stdc++.h>
using namespace std;
int qmi(int a, int k, int p) {
long long res = 1;
while (k) {
if (k & 1) res = res * a % p;
k >>= 1;
a = (long long)a * a % p; //a * a的结果可能会超过int范围
}
return res;
}
int main() {
int n;
cin >> n;
while (n--) {
int a, k, p;
cin >> a >> k >> p;
cout << qmi(a, k, p) << endl;
}
return 0;
}
题目2:求逆元,即求b^(p-2) % p的值。
逆元的定义:
若整数b和整数p互质(即它们俩的最大公约数为1),并且对于任意的整数a,如果满足b|a(即a能整除b),则存在一个整数x,使得 a / b ≡ a × x ( m o d p ) a/b \equiv a \times x \ (mod \ p) a/b≡a×x (mod p),则称x为b模p的乘法逆元。
b存在乘法逆元的充分必要条件是b与p互质。
特别的,如果p是质数时,那么 b p − 2 b^{p-2} bp−2即是b模p的乘法逆元。
#include <iostream>
using namespace std;
int n;
int qmi(int a, int k, int p) {
long long res = 1;
while (k) {
if (k & 1) res = (long long)res * a % p;
k >>= 1;
a = (long long)a * a % p;
}
return res;
}
int main() {
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;
}