一.主要思想:
找到一个素数后,就将它的倍数标记为合数,也就是把它的倍数“筛掉”;如果一个数没有被比它小的素数“筛掉”,那它就是素数。
二.代码实现:
#include <iostream>
#include <cstring>
using namespace std;
const int MAX_SIZE=200;
bool isprime[MAX_SIZE];
int prime[MAX_SIZE];//现在已经筛出的素数列表
int n,cnt=0;//cnt表示已经筛出的素数个数
void euler(){
memset(isprime,true,sizeof(isprime));
isprime[1]=false;
for(int i=2;i<=n;i++){
if(isprime[i]){//如果i没有被前面的数筛掉,则i是素数
prime[++cnt]=i;
}
for(int j=1;j<=cnt&&i*prime[j]<=n;++j){
isprime[i*prime[j]]=false;
if(i%prime[j]==0)
break;
}
}
}
三.实战演练 :
1.题目描述:
定义F(i)表示1-i中与i互质的数的个数。现给定一个正整数N,请你求出
2.输入描述:
第一行为一个整数T,表示测试数据数量。
接下来的T行,每行包括一个正整数N。
3.输出描述:
输出共T行,每行包含一个整数,表示答案。
4.代码实现:
#include <iostream>
#include <cstring>
using namespace std;
const long long N=1e7+10;
long long prime[N],eulers[N],cnt=0;
bool isprime[N];
void euler(long long n){
memset(isprime,true,sizeof(isprime));
isprime[1]=false;
eulers[1]=1;
for(long long i=2;i<=n;i++){
if(isprime[i]){
prime[++cnt]=i;
eulers[i]=i-1;
}
//遍历所有的质数
for(long long j=1;j<=cnt&&i*prime[j]<=n;j++){
isprime[i*prime[j]]=false;
if(i%prime[j]==0){
eulers[prime[j]*i]=eulers[i]*prime[j];
break;
}
eulers[prime[j]*i]=eulers[i]*(prime[j]-1);
}
}
}
int main(int argc, const char * argv[]) {
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
euler(N);
for(long long i=2;i<=N;i++){
eulers[i]+=eulers[i-1];
}
long long t,n;
cin>>t;
for(long long i=0;i<t;i++){
cin>>n;
cout<<eulers[n]<<'\n';
}
return 0;
}