欧拉定理
欧拉定理(Euler's Totient Theorem)
一、核心思想:指数的周期性
在模 \(n\) 运算上,不断地用一个数 \(a\) 去乘以自己时(即 \(a, a^2, a^3, \dots\)),会发现结果会呈现出周期性循环。
欧拉定理对这个循环的长度给出了一个明确的结论:
只要 \(a\) 和 \(n\) 互质,那么 \(a\) 的 \(\phi(n)\) 次方模 \(n\) 的结果,必然是 \(1\)。
这里的 \(\phi(n)\) 就是欧拉函数。
二、定理的正式表述
如果整数 \(a\) 和 正整数 \(n\) 满足 \(\gcd(a,n)=1\)(即它们互质),那么:\(a^{\phi(n)} \equiv 1 \pmod{n}\)。
这个定理是费马小定理的推广。当 \(n\) 是一个质数 \(p\) 时,\(\phi(p) = p-1\),定理就变成了 \(a^{p-1} \equiv 1 \pmod{p}\),这正是费马小定理。
三、应用:降幂
这个定理的厉害之处在于,能把很大的指数给降下来。既然 $a^{\phi(n)} 等于 \(1\),那么 \(a\) 的 \(k \cdot \phi(n)\) 次方也等于 \(1\)。这意味着指数 \(b\) 可以对 \(\phi(n)\) 取模。
所以,计算 \(a^b \bmod n\) 时,可以把它简化为:\(a^b \equiv a^{b \bmod \phi(n)} \pmod{n}\)。
例子:计算 \(3^{100} \bmod 7\)。
- 检查条件:\(\gcd(3,7)=1\),互质。满足条件。
- 计算 \(\phi\) 值:\(7\) 是质数,\(\phi(7)=7-1=6\)。
- 降幂:指数 \(100\) 可以对 \(6\) 取模。\(100 \bmod 6 = 4\)。
- 简化问题:原问题等价于计算 \(3^4 \bmod 7\)。
- 计算:\(3^4 = 81\)。\(81 \div 7 = 11 \cdots 4\)。
- 答案:\(3^{100} \bmod 7 = 4\)。
扩展欧拉定理(Extended Euler's Theorem)
一、为什么需要“扩展”?
欧拉定理有一个严格的限制:\(a\) 和 \(n\) 必须互质。那如果不互质怎么办?比如计算 \(6^{100} \bmod 10\),\(\gcd(6,10)=2\),欧拉定理就没法直接用了。
扩展欧拉定理就是来解决这个问题的。它是一个更通用的版本,对 \(a\) 和 \(n\) 没有任何限制。
二、定理的正式表述
对于任意整数 \(a\) 和正整数 \(n\),分情况讨论指数 \(b\):
- 当 \(b \lt \phi(n)\) 时:
- 指数 \(b\) 还不够大,可能还没进入“循环节”。
- 这时候不能降幂,老老实实直接计算。
- 当 \(b \ge \phi(n)\) 时:
- 指数 \(b\) 足够大,保证它已经进入了数字的循环节。
- 这时候就可以安全地降幂了,但公式稍微有点不同。
- \(a^b \equiv a^{b \bmod \phi(n) + \phi(n)} \pmod{n}\)。
注意这个 \(+ \phi(n)\)。这是扩展欧拉定理的精髓,也是和标准欧拉定理唯一的区别。
为什么要 \(+ \phi(n)\)?这是一个“安全措施”。因为当 \(a\) 和 \(n\) 不互质时,幂的循环可能不会从 \(a^0=1\) 开始。前面可能有一小段“尾巴”不参与循环。\(b \bmod \phi(n)\) 可能会得到一个很小的数,这可能会跳回到“尾巴”上。而 \(b \bmod \phi(n) + \phi(n)\) 保证了新的指数一定大于等于 \(\phi(n)\),安全地留在循环节内。
例子:计算 \(6^{100} \bmod 10\)
- 检查条件:\(\gcd(6,10)=2\),不互质。必须用扩展欧拉定理。
- 计算 \(\phi\) 值:\(\phi(10)= 10 \times (1-1/2) \times (1-1/5) = 4\)。
- 比较指数:指数 \(b=100\),\(\phi(10)=4\)。因为 \(100 \ge 4\),适用第二种情况。
- 降幂:\(100 \bmod 4 = 0\)。新的指数是 \(0 + \phi(10) = 4\)。
- 简化问题:原问题等价于计算 \(6^4 \bmod 10\)。
- 计算:\(6^1=6, 6^2=36 \equiv 6, 6^3 \equiv \dots 6\)。\(6\) 的任意正整数次幂模 \(10\) 都是 \(6\)。所以 \(6^4 \bmod 10 = 6\)。
- 答案:\(6^{100} \bmod 10 = 6\)。
习题:P5091 【模板】扩展欧拉定理
解题思路
先求 \(\phi(m)\),然后求 \(b \bmod \phi(m)\),在拼数的过程中取余来求。
中间判断一下拼数的过程中是否出现了 \(\ge \phi(m)\) 的情况。如果没出现,就是 \(b \lt \phi(m)\) 的情况,也就是要求 \(a^b\),否则最后是求 \(a^{b \bmod \phi(m) + \phi(m)}\)。
参考代码
#include <cstdio>
const int N = 20000005;
char s[N];
int calcPhi(int x) {
int res = x;
int i = 2;
while (i * i <= x) {
if (x % i == 0) {
res = res / i * (i - 1);
while (x % i == 0) x /= i;
}
i++;
}
if (x > 1) res = res / x * (x - 1);
return res;
}
int qpow(int x, int y, int mod) {
int res = 1;
while (y > 0) {
if (y & 1) res = 1ll * res * x % mod;
x = 1ll * x * x % mod;
y >>= 1;
}
return res;
}
int main()
{
int a, m; scanf("%d%d%s", &a, &m, s);
int phi = calcPhi(m);
int b = 0;
bool big = false;
for (int i = 0; s[i]; i++) {
b = b * 10 + s[i] - '0';
if (b >= phi) {
b %= phi; big = true;
}
}
if (big) b += phi;
printf("%d\n", qpow(a, b, m));
return 0;
}

浙公网安备 33010602011771号