欧拉降幂公式
在数论中,欧拉降幂公式是一个强大的工具,用于简化大指数模运算。公式如下:
∀k>φ(m),有Ak≡Akmodφ(m)+φ(m)(modm)成立。\forall k > \varphi(m),有 A^k \equiv A^{k \mod \varphi(m) + \varphi(m)} \pmod{m} 成立。 ∀k>φ(m),有Ak≡Akmodφ(m)+φ(m)(modm)成立。
其中:
- AAA 和 mmm 是正整数
- φ(m)\varphi(m)φ(m) 是欧拉函数
- kkk 是指数,且 k>φ(m)k > \varphi(m)k>φ(m)
这个公式允许我们将非常大的指数 kkk 降低到可计算的范围,从而高效地计算模幂。
欧拉函数
欧拉函数 φ(n)\varphi(n)φ(n) 表示小于或等于 nnn 的正整数中与 nnn 互质的数的个数。例如:
- φ(1)=1\varphi(1) = 1φ(1)=1
- φ(2)=1\varphi(2) = 1φ(2)=1(因为1与2互质)
- φ(3)=2\varphi(3) = 2φ(3)=2(因为1和2与3互质)
- φ(4)=2\varphi(4) = 2φ(4)=2(因为1和3与4互质)
- 如果 mmm 是质数,则φ(m)=m−1\varphi(m) = m - 1φ(m)=m−1
计算欧拉函数 φ(n)\varphi(n)φ(n) 的代码:
int euler(int n) {int ans = n; // 初始化结果为nfor (int i = 2; i * i <= n; ++i) // 遍历2到√nif (n % i == 0) { // 如果i是n的质因数ans = ans / i * (i - 1); // 应用公式:ans *= (1 - 1/i)while (n % i == 0) // 除去所有i因子n /= i;}if (n > 1) // 处理剩余的大于√n的质因数ans = ans / n * (n - 1);return ans;
}
原理基于质因数分解,欧拉函数是积性函数,即如果 mmm 和 nnn 互质,则 φ(mn)=φ(m)⋅φ(n)\varphi(mn) = \varphi(m) \cdot \varphi(n)φ(mn)=φ(m)⋅φ(n)。对于任意正整数 mmm,其欧拉函数可以通过以下公式计算:
φ(m)=m∏p∣m(1−1p)\varphi(m) = m \prod_{p | m} \left(1 - \frac{1}{p}\right)φ(m)=mp∣m∏(1−p1)
时间复杂度 O(sqrt(n))O(sqrt(n))O(sqrt(n))
例题
洛谷P12847 [蓝桥杯 2025 国 A] 斐波那契数列
AC代码:
(这里还用到了矩阵快速幂求斐波那契数列,以及斐波那契前n项和的知识)
#include <bits/stdc++.h>
using namespace std;
const int MOD = 998244353 - 1;long long qpow(long long a, long long b) {long long res = 1;while (b > 0) {if (b & 1)res = res * a % (MOD + 1);a = a * a % (MOD + 1);b >>= 1;}return res;
}struct Matrix { // 矩阵结构体2x2long long m[2][2];Matrix() { memset(m, 0, sizeof(m)); }
};// 矩阵乘法(优化版)
Matrix multiply(const Matrix &a, const Matrix &b) {Matrix res;for (int i = 0; i < 2; ++i) {for (int j = 0; j < 2; ++j) {for (int k = 0; k < 2; ++k) {res.m[i][j] = (res.m[i][j] + a.m[i][k] * b.m[k][j]) % MOD;}}}return res;
}// 矩阵快速幂
Matrix matrix_pow(Matrix mat, long long power) {Matrix result;result.m[0][0] = result.m[1][1] = 1; // 单位矩阵while (power > 0) {if (power & 1) {result = multiply(mat, result);}mat = multiply(mat, mat);power >>= 1;}return result;
}// 计算斐波那契数(从F(1)=1开始)
long long fibonacci(long long n) {if (n == 0)return 0;if (n == 1 || n == 2)return 1;Matrix base;base.m[0][0] = base.m[0][1] = base.m[1][0] = 1;Matrix result = matrix_pow(base, n - 2);return (result.m[0][0] + result.m[0][1]) % MOD;;
}int main() {long long n;cin >> n;if (n == 1) {cout << 2 << endl;} else if (n == 2) {cout << 6 << endl;} else {/*斐波那契数列的前n项和:S(n) = F(n+2)-1*/int p2 = (1 + fibonacci(n - 2 + 2) - 1) % MOD + MOD;int p3 = (fibonacci(n - 1 + 2) - 1) % MOD + MOD;cout << qpow(2, p2) * qpow(3, p3) % (MOD + 1) << endl;}return 0;
}