欧拉函数
欧拉函数
1、定义:用 \(\varphi (n)\) 表示的是小于等于 \(n\) 和 \(n\) 互质的个数,比如说 \(\varphi(1) = 1、\varphi(2)=1\),当 \(n\) 为质数时,很显然 \(\varphi(n)=n-1\)。
2、性质:
-
欧拉函数是积性函数,即对于所有的 \(gcd(a,b)=1\),都有 \(\varphi(ab)=\varphi(a)\varphi(b)\) ;特别的,当 \(n\) 为奇数时,有 \(\varphi(2n)=\varphi(n)\varphi(2)=\varphi(n)\) ;另外还有个很重要的积性函数,即 \(id(n)=\sum_{d|n}\varphi(d)=n(莫比乌斯方面的知识)\) 。
-
若 \(n=p^k\),其中 \(p\) 为质数,那么 \(\varphi(n)=p^{k}-p^{k-1}\) 。
-
有唯一分解定理得:对于任意的 \(n\) 都能写成 \(n=\prod_{i=1}^{s}p_i^{k_i}\),其中 \(p_i\) 为质数,有 \(\varphi(n)=n\prod_{i=1}^{s}\frac{p_i-1}{p_i}\) ,推理过程就是利用积性函数的性质推理的。
3、质因数分解求欧拉函数值:\(O(\sqrt n)\)
template<typename T>
struct getphi{
inline T calc(T x) {
T ans = x;
for (T i = 2; i <= x / i; i++) {
if (x % i == 0) {
ans = ans / i * (i - 1);
while (x % i == 0) x /= i;
}
}
if (x > 1) ans = ans / x * (x - 1);
return ans;
}
};
getphi<i64> ph;
4、优化版本后的求解:比前面的时间复杂度来的更低
template<typename T>
struct pre{
int N;
vector<T> preim;
vector<T> a;
pre(int N_) : a(N_ + 1) {
N = N_;
for (T 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(T x) {
return (a[x] == x && x != 0);
}
};
pre d(100000);
template<typename T>
struct getphi{
inline T calc(T x) {
T ans = x;
for (auto p : d.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<i64> ph;
5、线性筛求解:\((积性函数)\) 线性预处理欧拉函数,时间复度为:\(O(n)\)
template<typename T>
struct getphi{
int N;
vector<T> preim;
vector<T> a;
vector<T> phi;
getphi(int N_) : a(N_ + 1), phi(N_ + 1) {
N = N_;
phi[1] = 1;
for (T 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];
}
}
}
};

浙公网安备 33010602011771号