欧拉降幂
欧拉函数:
$\varphi(N) $ : 小于等于 N 且与 N 互质的正整数的个数
给出公式:
$\varphi(N) = N \times \frac{p_1-1}{p_1} \times \frac{p_2-1}{p_2} \times \dots \times \frac{p_m-1}{p_m}$
根据容斥原理 或 $\varphi(N) $为积性函数的性质可证明
欧拉定理:
对于整数 $m > 0$ 和整数 $a$ ,且 $\gcd(a,m)=1$ ,有:
$a^{\varphi(m)} \equiv 1 \pmod{m}$
扩展欧拉定理:
$a^b \equiv \begin{cases} a^b, & b < \varphi(m) \\ a^{(b \bmod \varphi(m)) + \varphi(m)}, & b \ge \varphi(m) \end{cases} \pmod{m}$
例题:P1405 苦恼的小明 - 洛谷
题意:
求:$a_1^{a_2^{a_3^{\cdots^{a_n}}}}$ mod10007 的值
思路:
为方便表达,这里把用 m 代表模数 10007
一、从最终目标倒推
我们要计算:$\text{ans} = a_1^{\,a_2^{\,a_3^{\,\cdots^{a_n}}}} \bmod m$
设整个幂塔为$P(1, n)$,其中$P(i, n) = a_i^{\,a_{i+1}^{\,\cdots^{a_n}}}$。
那么:
$P(1, n) = a_1^{\,P(2, n)} \bmod m$
二、应用欧拉降幂
根据扩展欧拉定理(当指数足够大时):
$a_1^{\,P(2, n)} \bmod m = a_1^{\,P(2, n) \bmod \varphi(m) + \varphi(m)} \bmod m$
关键:要计算这个值,我们需要知道$P(2, n) \bmod \varphi(m)$。
所以,问题转化为计算:
$P(2, n) \bmod \varphi(m)$
其中$P(2, n) = a_2^{\,a_3^{\,\cdots^{a_n}}}$。
三、递归继续
计算$P(2, n) \bmod \varphi(m)$又是一个相同形式的问题:
$P(2, n) \bmod \varphi(m) = a_2^{\,P(3, n)} \bmod \varphi(m)$
再次应用欧拉降幂,我们需要知道$P(3, n) \bmod \varphi(\varphi(m))$。
四、模式出现了
$\begin{aligned}&\text{第1层(最外层)需要模数} \varphi^{(1)}(m) = m \\&\text{第2层需要模数} \varphi^{(2)}(m) = \varphi(m) \\&\text{第3层需要模数} \varphi^{(3)}(m) = \varphi(\varphi(m)) \\&\ldots \\&\text{第}k\text{层需要模数} \varphi^{(k)}(m)\end{aligned}$
其中$\varphi^{(k)}(m)$表示对$m$连续应用$k-1$次$\varphi$函数。
代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<queue>
#include<deque>
#include<stack>
#include<set>
#include<map>
#include<bitset>
#include<tuple>
#include<unordered_map>
#define inf 72340172838076673
#define endl '\n'
#define F first
#define S second
#define mst(a,x) memset(a,x,sizeof (a))
using namespace std;
typedef pair<int, int> pii;
const int N = 1234568, m = 10007;
int n;
int h[N];
int M[20];
int getphi(int x) {
int res = x;
for (int i = 2; i <= sqrt(x); i++) {
if (x % i == 0) {
res = res / i * (i - 1);
while (x % i == 0) x /= i;
}
}
if (x > 1) res = res / x * (x - 1);
return res;
}
int mod(int a, int b) {
if (a >= b) return a % b + b;
return a;
}
int qpow(int a, int b, int m) {
int res = 1;
while (b) {
if (b & 1) res = mod(res * a, m);
a = mod(a * a, m);
b >>= 1;
}
return res;
}
void solve() {
cin >> n;
for (int i = 1; i <= n; i++) cin >> h[i];
int idx = 0;
M[++idx] = m;
while (M[idx] > 1) {
M[idx + 1] = getphi(M[idx]);
idx++;
}
for (int i = n; i >= 2; i--) {
int mi = min(i - 1, idx);
h[i - 1] = qpow(h[i - 1], h[i], M[mi]);
}
cout << h[1] % m << endl;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int T = 1;
// cin >> T;
while (T--) solve();
return 0;
}

浙公网安备 33010602011771号