上帝与集合的正确用法
题意
给定一个数字 p p p,求:
2 2 2 ⋯ m o d p 2^{2^{2^{\cdots}}} \bmod p 222⋯modp
思路
因为可能存在 p p p与2不互质的情况,所以要使用扩展欧拉定理。
使用扩展欧拉定理构造一个同余式子:
2 2 2 ⋯ ≡ 2 2 2 2 ⋯ m o d φ ( p ) + φ ( p ) ( m o d p ) 2^{2^{2^{\cdots}}} \equiv 2^{ 2^{2^{2^{\cdots}}} \bmod \varphi(p) + \varphi(p) } \pmod p 222⋯≡2222⋯modφ(p)+φ(p)(modp)
如果把上面个那个幂在展开的话,会得到:
2 2 2 ⋯ ≡ 2 2 2 2 ⋯ m o d φ ( φ ( p ) ) + φ ( φ ( p ) ) ( m o d φ ( p ) ) 2^{2^{2^{\cdots}}} \equiv 2^{ 2^{2^{2^{\cdots}}} \bmod \varphi(\varphi(p)) + \varphi(\varphi(p)) } \pmod {\varphi(p)} 222⋯≡2222⋯modφ(φ(p))+φ(φ(p))(modφ(p))
仔细看的话,其实就是套娃,一层一层的套娃。因此,可以直接通过递归,一层一层算到欧拉函数为1的时候,返回0。(任何数模1结果都是0)。
代码
一种可行的c++代码。
#include <bits/stdc++.h>
using ll = long long;
inline ll mul(ll a, ll b, ll p) {
a = (a % p + p) % p;
b = (b % p + p) % p;
ll d = static_cast<long double>(a) * b / p;
d = a * b - d * p;
if (d < 0)
d += p;
if (d > p)
d -= p;
return d;
}
inline ll power(ll a, ll i, ll p) {
ll res = 1 % p;
while (i) {
if (i & 1)
res = mul(res, a, p);
a = mul(a, a, p);
i >>= 1;
}
return res;
}
const int MAXN = 1e7 + 1;
std::vector<int>prime;
int phi[MAXN];
bool vis[MAXN];
ll work(ll x) {
if (x == 1)
return 0;
return power(2, work(phi[x]) + phi[x], x);
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
phi[1] = 1;
for (int i = 2; i <= 1e7; ++ i) {
if (!vis[i]) {
prime.push_back(i);
phi[i] = i - 1;
}
for (int j = 0; j < prime.size(); ++ j) {
if (static_cast<long long>(i) * prime[j] >= 1e7) {
break;
}
vis[i * prime[j]] = true;
if (i % prime[j] != 0) {
phi[i * prime[j]] = phi[i] * phi[prime[j]];
} else {
phi[i * prime[j]] = phi[i] * prime[j];
break;
}
}
}
int t;
std::cin >> t;
while (t --) {
ll x;
std::cin >> x;
std::cout << work(x) << '\n';
}
return 0;
}

本文介绍了一道编程题目,涉及利用扩展欧拉定理解决关于集合的数学问题。当给定数字p时,需要计算2的幂次模p的结果。通过递归应用扩展欧拉定理,可以解决当p与2不互质时的情况,直至欧拉函数值为1。
1685

被折叠的 条评论
为什么被折叠?



