拓展欧拉定理
基础概念
欧拉定理
对于正整数 \(a\) 和 \(m\),若满足 \(gcd(a,m)=1\),则 \(a^{\varphi(m)}\equiv1~(mod~m)\)。\(\varphi(m)\) 为 \(m\) 的欧拉函数。
拓展欧拉定理
在 \((mod~m)\) 的前提下,
\[a^b\equiv\begin{cases}
a^b&,b<\varphi(m)\\
a^{b~mod~\varphi(m)+\varphi(m)}&,b\ge\varphi(m)
\end{cases}
\]
利用拓展欧拉定理,在求大次幂 \(a^b\) 时,可以先降幂,再用快速幂求解。步骤:
- 先求出 \(m\) 的欧拉函数。见博客 欧拉函数。
- 再利用拓展欧拉定理进行降幂,代码如下:
string b; // b是幂,因为很大,所以用字符串存
// 降幂
int depow(int phi)
{
bool flag = false;
ll sum = 0;
for (char ch : b)
{
sum = sum * 10 + ch - '0';
if (sum >= phi)
{
sum %= phi;
flag = true;
}
}
if (flag) sum += phi;
return sum;
}
- 再用快速幂求解。见博客 快速幂。
例题
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int a, m;
string b;
// 求欧拉函数
int get_phi(int n)
{
ll res = n;
for (int i = 2; (ll)i * i <= n; ++i)
{
if (n % i == 0)
{
res = res * (i - 1) / i;
while (n % i == 0) n /= i;
}
}
if (n > 1) res = res * (n - 1) / n;
return res;
}
// 降幂
int depow(int phi)
{
bool flag = false;
ll sum = 0;
for (char ch : b)
{
sum = sum * 10 + ch - '0';
if (sum >= phi)
{
sum %= phi;
flag = true;
}
}
if (flag) sum += phi;
return sum;
}
// 快速幂
int qpow(int x, int n, int m)
{
ll res = 1;
while (n > 0)
{
if (n & 1)
res = res * x % m;
x = (ll)x * x % m;
n >>= 1;
}
return res;
}
int main()
{
#ifdef LOCAL
freopen("test.in", "r", stdin);
#endif
cin >> a >> m >> b;
int phi = get_phi(m);
int n = depow(phi);
cout << qpow(a, n, m) << endl;
return 0;
}
完