欧拉筛法(phi,d,prime)

时间:2025-01-08 18:35:20

筛法求素数的核心就是让每个合数被它的最小质因子筛掉,那么剩下来的就是素数了。

于是在这个过程中我们可以顺便求出每个数的φ()、d()、e()。

ϕ:小于等于该数的与它互质的数的个数(一个数与其自身互质)
d:该数的正因数个数   
e:该数最小质因数的个数

其中上述三个函数均为不完全积性函数(即当x、y互质时才有f(xy)=f(x)f(y)),因此在筛法筛这三个函数时要有分情况讨论。

当x、y不互质时,φ(xy)=φ(x) y,其中y是x最小质因数(即)。由φ的通式可得:φ(xy)=xy(1-1/p1)(1-1/p2)…=xφ(y),所以在用最小素因子筛时就可求了。

当x、y不互质时,由d的通式(上百科自查吧)可得d(xy)=d(x)[e(x)+2]/[e(x)+1]。

当x、y不互质时,若x是y的最小质因数,则e(xy)=e(y)+1。

 下面就是代码了——

 #include<bits/stdc++.h>
using namespace std;
const int N = ;
int prime[N], e[N], d[N], tot, phi[N];
bool not_p[N];
inline void pre(){
not_p[] = ;
d[] = ;
for(int i = ; i < N; ++i){
if(!not_p[i]) {
++tot, prime[tot] = i;
e[i] = , d[i] = ; phi[i] = i - ;
}
for(int j = ; j <= tot; ++j){
int k = prime[j] * i;
if(k > N) break;
not_p[k] = ;
if(i % prime[j]) {
d[k] = d[i] * d[prime[j]];
e[k] = ;
phi[k] = phi[i] * phi[prime[j]];
}
else{
d[k] = d[i] / (e[i] + ) * (e[i] + );
e[k] = e[i] + ;
phi[k] = phi[i] * prime[j];
break;
}
}
}
}
int main(){
pre();
printf("phi:\n");
for(int i = ; i < N; ++i){
printf("%d\n", phi[i]);
}
printf("d:\n");
for(int i = ; i < N; ++i){
printf("%d\n", d[i]);
}
printf("prime:\n");
for(int i = ; i <= tot; ++i){
printf("%d\n", prime[i]);
}
return ;
}