「扩展欧拉定理」P5091 【模板】扩展欧拉定理
知识点: 扩展欧拉定理
原题面
题意简述
给定 \(a,b,m\),求 \(a^b\pmod m\)。
\(1\le a \le 10^9, 1\le b\le 10^{20000000}, 1\le m\le 10^8\)。
分析题意
草 \(b\) 后面这是一大串什么啊。
直接做必爆炸,考虑用什么东西来降幂。
发现模数 \(m\) 较小,\(O(m)\) 可过,考虑使复杂度只与 \(m\) 有关。
考虑扩展欧拉定理。
需要先求得 \(\varphi(m)\) 的值。
考虑欧拉函数的性质,有下式:
\(m\) 的一质因子 \(p_i\) 对 \(\varphi (m)\) 的贡献为 \(\dfrac{p_i-1}{p_i}\)。
考虑质因数分解 \(m\),试除即可。
注意不要遗漏 \(\ge \sqrt{m}\) 的至多一个质因子。
求得 \(\varphi(m)\) 后,套用公式降幂即可。
可使用快速幂进一步优化复杂度。
总复杂度 \(O(\sqrt{m} + \log m)\)。
代码实现
//知识点:欧拉定理
/*
By:Luckyblock
*/
#include
#include
#include
#include
#define ll long long
//=============================================================
int a, b, m, phi, ans = 1;
bool flag;
//=============================================================
inline int read() {
int f = 1, w = 0; char ch = getchar();
for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
for (; isdigit(ch); ch = getchar()) {
w = (w << 3) + (w << 1) + (ch ^ '0');
if (w >= phi) {
flag = true;
w %= phi;
}
}
return f * w;
}
void GetMax(int &fir, int sec) {
if (sec > fir) fir = sec;
}
void GetMin(int &fir, int sec) {
if (sec < fir) fir = sec;
}
void GetPhi() {
int tmp = m; //用于质因数分解
phi = m;
for (int i = 2; i * i <= m; ++ i) {
if (! (tmp % i)) {
phi = phi - phi / i; //即 phi = phi*(1-1/i)
while (! (tmp % i)) tmp /= i;
}
}
if (tmp > 1) phi = phi - phi / tmp;
}
int QuickPow(int x, int y) {
int ret = 1;
while (y) {
if (y & 1) ret = 1ll * ret * x % m;
x = 1ll * x * x % m, y >>= 1;
}
return ret;
}
//=============================================================
int main() {
scanf("%d%d", &a, &m);
GetPhi();
b = read();
if (flag) b += phi;
printf("%d", QuickPow(a, b));
return 0;
}