题目地址:
https://www.luogu.com.cn/problem/P5091
题目描述:
给你三个正整数
a
,
m
,
b
a,m,b
a,m,b,你需要求:
a
b
m
o
d
m
a^b \bmod m
abmodm
输入格式:
一行三个整数,
a
,
m
,
b
a,m,b
a,m,b
输出格式:
一个整数表示答案
注意输入格式,
a
,
m
,
b
a,m,b
a,m,b 依次代表的是底数、模数和次数
数据范围:
对于
100
%
100\%
100%的数据,
1
≤
a
≤
1
0
9
1\le a \le 10^9
1≤a≤109,
1
≤
b
≤
1
0
20000000
,
1
≤
m
≤
1
0
8
1\le b \le 10^{20000000},1\le m \le 10^8
1≤b≤1020000000,1≤m≤108。
扩展欧拉定理是,如果 b > ϕ ( m ) b>\phi(m) b>ϕ(m),则有: a b ≡ a b m o d ϕ ( m ) + ϕ ( m ) ( m o d m ) a^b\equiv a^{b\bmod \phi(m)+\phi(m)}(\mod m) ab≡abmodϕ(m)+ϕ(m)(modm)若 b ≤ ϕ ( m ) b\le \phi(m) b≤ϕ(m),则可以直接用快速幂暴力求解。证明比较复杂,略。代码如下:
#include <iostream>
using namespace std;
long a, b, m;
long fast_pow() {
long res = 1;
while (b) {
if (b & 1) res = res * a % m;
b >>= 1L;
a = a * a % m;
}
return res;
}
int main() {
scanf("%ld%ld", &a, &m);
long phi = m, tmp = m;
for (int i = 2; i <= tmp / i; i++) {
if (tmp % i == 0) {
phi = phi / i * (i - 1);
while (tmp % i == 0) tmp /= i;
}
}
if (tmp > 1) phi = phi / tmp * (tmp - 1);
char ch;
bool flag = false;
while (!isdigit(ch = getchar()));
for (; isdigit(ch); ch = getchar()) {
b = b * 10 + ch - '0';
if (b > phi) {
flag = true;
b %= phi;
}
}
if (flag) b += phi;
printf("%ld\n", fast_pow());
}
时间复杂度 O ( m + log b ) O(\sqrt m+\log b) O(m+logb),空间 O ( 1 ) O(1) O(1)。