欧拉筛法需要解决几个问题:
1.每个素数都会被留下;
答:显然。
2.每个合数都会被去掉(且只去掉一次);
答:设n=k * prime[ j ],当i枚举到n的时候
筛掉了n * prime[j+1],n * prime[ j+1]=k * prime[ j ]*prime[ j+1],
这个时候的最小质因数为prime[j],如果我们这个时候不break,当我们枚举到k * prime[j+1]的时候,也会再次筛一次,这个时候break的话可以保证只筛了一次。
而且根据分解定理,合数一定可以被分解为两个(至少两个)的质数的乘积,所以我们一定能把所有的合数都去掉。
3.及时终止;
<=n/i保证了及时终止和不会RE
~~**最后附上一道欧拉函数练习题**
给定一个正整数n,求1~n中每个数的欧拉函数之和。
输入格式
共一行,包含一个整数n。
输出格式
共一行,包含一个整数,表示1~n中每个数的欧拉函数之和。
数据范围
1≤n≤106
#include <bits/stdc++.h>
using namespace std;
const int N=1E6+50;
int n;
typedef long long ll;
bool jud[N];
int prime[N];
int cnt;
ll ji[N];
ll res;
int main(){
cin.tie(0);
cin>>n;
ji[1]=1;
for(int i=2;i<=n;i++){
if(!jud[i]){
prime[cnt++]=i;
ji[i]=i-1;
}
for(int j=0;prime[j]<=n/i;j++){
jud[prime[j]*i]=1;
if(i%prime[j]==0){
ji[i*prime[j]]=prime[j]*ji[i];
break;
}
ji[i*prime[j]]=(prime[j]-1)*ji[i];
}
}
for(int i=1;i<=n;i++){
res+=ji[i];
}
cout<<res;
return 0;
}