素数--求1-n之间有多少个素数(自用)

问题:输入正整数N,求1~N范围内素数的个数,2≤N≤1,000,000

样例输入: 

10000

样例输出: 

1229

1.定义法

#include <bits/stdc++.h>
using namespace std;
int isprime(int n){
	for(int i =2;i<=n/i;i++){
		if(n%i==0){
			return 0;
		}
	}
	return 1;
}
int main(){
	long long n;
	cin>>n;
	int cnt =0; 
	for(long long i =2;i<=n;i+=2){
		if(isprime(i)){
			cnt++;
		}
	}
	cout<<cnt;
}

2.朴素筛法

#include <bits/stdc++.h>
using namespace std;
//bitset<N> bitset1; // 创建一个长度为 N 的 bitset,所有位都被初始化为 0
const int maxn = 1e6+10;  //常数的定义
bitset <maxn> pri;    //1:合数  0:素数 
int isprime(int n){
	for(int i =2;i<=n/i;i++){
		if(n%i==0){         //合数 
			return 0;
		}
	}
	return 1;        //素数 
}
int main(){
	long long n;
	cin>>n;
	int cnt = 0;
	for(int i =2;i<=sqrt(n);i++){
		if(isprime(i)){       //i是素数,对i的倍数进行合数判定
		for(int j = 2*i;j<=n;j+=i) 
			pri[j] = 1;	
		}
	}
	for(int i =2;i<=n;i++){
		if(!pri[i]){
			cnt++;
		}
	}
	cout<<cnt<<endl;
}

3.埃氏筛法(在朴素筛法基础上进行)

#include <bits/stdc++.h>
using namespace std;
//bitset<N> bitset1; // 创建一个长度为 N 的 bitset,所有位都被初始化为 0
const int maxn = 1e6+10;  //常数的定义
bitset <maxn> pri;    //1:合数  0:素数 
int main(){
	long long n;
	cin>>n;
	int cnt = 0;
	for(int i =2;i<=sqrt(n);i++){
		if(!pri[i]){      //更快且不需要进行素数判断因为2为最小素数从小到i若i没有被筛掉则说明i是素数 
		for(int j =i*i;j<=n;j+=i)
		//因为2*i 当i等于2时已经有过2*3等等则当i等于3时则不需要再次进行2*i直接从i*i开始即可 
			pri[j] = 1;	
		}
	}
	for(int i =2;i<=n;i++){
		if(!pri[i]){
			cnt++;
		}
	}
	cout<<cnt<<endl;
}

4.欧拉筛法(最快)

埃氏筛选的弊端

举例说明:


120 在埃氏筛选中存在多次被筛

120 = 2*2*2*3*5

当i=2时被筛一次,当i=3时被筛一次,当i=5,6,8等等又会被筛一次,重复多次的被筛选,而欧拉筛选则是解决上述弊端的


具体见代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn =1e6+10;
bitset<maxn> pri;  //0:素数   1:合数
int primes[maxn],pp=0; 
int main(){
	int n,cnt =0;
	cin>>n;
	for(int i =2;i<=n;++i){
		if(!pri[i]){      //i:素数 
			primes[++pp] = i;
            cnt++;
		}
		for(int j = 1;primes[j]*i <= n;++j){
				pri[primes[j] * i] = 1;
				if(i%primes[j] == 0) break;   //优化重点,用于限制i每次筛选的最大值 
		}
	}
	cout<<cnt<<endl;
	return 0;
}

总结:

        几种方法之间关联性比较强,步步优化,建议从头看起,不要一步见底!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值