扩展欧拉函数求模
扩展欧拉定理
1、定义:若 \(gcd(a,p)=1\),则 \(a^{\varphi(p)} \equiv 1 \ (mod \ p)\)。
2、扩展欧拉定理求模:
\(\left\{\begin{array}{l} a^{b \ mod \ \varphi(p)}, \qquad \qquad gcd(a,p)=1 \\ a^b, \qquad \qquad \qquad \quad gcd(a,p) \ne 1,b < \varphi(p) \\ a^{b \ mod \ \varphi(p) \ + \ \varphi(p)}, \quad \ \ \ gcd(a,p) \ne 1,b \ge \varphi(p) \end{array}\right.\)
3、扩展欧拉定理一般用于 \(b\) 很大的快速幂。
- 模版:洛谷P5091。
struct pre{
int N;
vector<i64> preim;
vector<i64> a;
pre(int N_) : a(N_ + 1) {
N = N_;
for (i64 i = 2; i <= N; i++) {
if (!a[i]) {
a[i] = i;
preim.push_back(i);
}
for (auto p : preim) {
if (i * p > N) break;
a[i * p] = p;
if (a[i] == p) {
break;
}
}
}
}
inline bool ispreim(i64 x) {
return (a[x] == x && x != 0);
}
};
pre t(1000000);
struct getphi{
inline i64 calc(i64 x) {
i64 ans = x;
for (auto p : t.preim) {
if (p * p > x) break;
if (x % p == 0) {
ans = ans / p * (p - 1);
while (x % p == 0) x /= p;
}
}
if (x > 1) ans = ans / x * (x - 1);
return ans;
}
};
getphi t2;
struct exphi{
inline i64 exqp(i64 a, string &s, i64 p = 1e9 + 7) {
i64 n = s.size();
i64 b = 0;
i64 phi = t2.calc(p);// 如果模数是一样的,可以把模数在全局变量中求出来即可
bool f = 0;
for (i64 i = 0; i < n; i++) {
b *= 10;
b += (s[i] - '0');
if (b >= phi) {
f = 1;
b %= phi;
}
}
if (__gcd(a, p) != 1 && f) b += phi;
a %= p;
i64 res = 1;
while (b) {
if (b & 1) res = res * a % p;
a = a * a % p;
b >>= 1;
}
return res;
}
};
另一种版本的扩展欧拉定理,主要处理 \(p\) 不超过 \(1e7\) 的模数
struct getphi{
int N;
vector<i64> preim;
vector<i64> a;
vector<i64> phi;
getphi(int N_) : a(N_ + 1), phi(N_ + 1) {
N = N_;
phi[1] = 1;
for (i64 i = 2; i <= N; i++) {
if (!a[i]) {
a[i] = i;
phi[i] = i - 1;
preim.push_back(i);
}
for (auto p : preim) {
if (i * p > N) break;
a[i * p] = p;
if (a[i] == p) {
phi[i * p] = phi[i] * p;
break;
}
phi[i * p] = phi[i] * phi[p];
}
}
}
};
getphi t(1000000);
struct exphi{
inline i64 exqp(i64 a, string &s, i64 p = 100007) {
int n = s.size();
i64 b = 0;
i64 phi = t.phi[p];
bool f = 0;
for (i64 i = 0; i < n; i++) {
b *= 10;
b += (s[i] - '0');
if (b >= phi) {
f = 1;
b %= phi;
}
}
if (__gcd(a, p) != 1 && f) b += phi;
i64 res = 1;
a %= p;
while (b) {
if (b & 1) res = res * a % p;
a = a * a % p;
b >>= 1;
}
return res;
}
};

浙公网安备 33010602011771号