扩展欧拉定理
P5091 扩展欧拉定理
题目大意:
给定三个数,a, b, m, 求a ^ b % m的值。
1 <= b <= 10^20000000
思路
b的值非常大,直接用快速幂求值会TLE
考虑用扩展欧拉定理,将b降幂之后,再使用快速幂快速求结果
扩展欧拉定理:
\[设 \ ( a, m \in \mathbb{Z}^+ \ ),则:
a^b \equiv
\begin{cases}
a^{b \bmod \phi(m)} &\pmod{m} & \text{若 } b < \phi(m), \\
a^{b \bmod \phi(m) + \phi(m)} &\pmod{m} & \text{若 } b \geq \phi(m).
\end{cases}
\]
代码
#include <bits/stdc++.h>
#define PRINT_PI(presision, value) std::cout << std::fixed << std::setprecision(presision) << (value) << std::endl
using u32 = unsigned;
using i64 = long long;
using u64 = unsigned long long;
// 求m的欧拉函数值
i64 get_phi(i64 m) {
i64 res = m;
for (int i = 2; i * i <= m; i ++) {
if (m % i == 0) { // 找到一个质因子
res = res / i * (i-1);
while (m % i == 0) m /= i; // 把当前质因子除尽
}
}
if (m > 1) res = res / m * (m-1); // 别忘了最后一个质因子
return res;
}
i64 depow(i64 phi, std::string b) {
// 扩展欧拉定理对b降幂,phi是模数的欧拉函数
i64 res = 0;
bool flag = false;
// 用秦九韶算法对b进行模m意义下的化简,即扩展欧拉定理中的b % m的那一步,因为b非常大,直接取模不好算,因此用秦九韶算法化简
for (int i = 0; b[i]; i ++) {
res = res * 10 + (b[i] - '0');
if (res >= phi) {
flag = true;
res %= phi;
}
}
// 最后加上phi(m)
if (flag) res += phi;
return res;
}
i64 qmi(i64 a, i64 b, i64 m) {
i64 res = 1;
while (b) {
if (b & 1) res = (res * a) % m;
a = (a * a) % m;
b >>= 1;
}
return res;
}
void solve() {
// register 用于将局部变量存储到寄存器中,提高访问速度
i64 a, m;
std::cin >> a >> m;
std::string b;
std::cin >> b;
// 求phi(m)的值:m的欧拉函数,用试除法
i64 phi = get_phi(m);
// 对b降幂
i64 bb = depow(phi, b);
// 用快速幂求a^b % m
std::cout << qmi(a, bb, m) << "\n";
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int t = 1;
// std::cin >> t;
while (t --) {
solve();
}
return 0;
}
本文来自博客园,作者:来杯whiskey,转载请注明原文链接:https://www.cnblogs.com/zj-cnbolgs/p/18882273
浙公网安备 33010602011771号