求素数个数(三种判断素数方法

description

求素数的个数。本题要求编写一个程序,求1~n的素数个数。 要求至少给出两种解法,对于相同的n,给出这两种解法的结果,通过相关数据进行测试,目的是通过对比同一问题不同解法的绝对执行时间体会如何设计“好”的算法。

输入格式:

输入在一行中给出1个整数n(<= 10 000 000)。

输出格式:

对每一组输入,在一行中输出1~n的素数个数。

输入样例1:

5

输出样例1:

3

输入样例2:

14

输出样例2:

6

solution

暴力法

传统方法,从2到n-1依次试,4,5,6测试点超时

#include <stdio.h>
int main(){
	int n, count = 0, flag;
	scanf("%d", &n);
	for(int i = 2; i <= n; i++){
		flag = 1;
		for(int j = 2; j < i; j++){
			if(i%j == 0){
				flag = 0;
				break;
			}
		}
		count += flag;
	}
	printf("%d", count);
	return 0;
}

开根号法:从2到sqrt(n)均整除判断(原因:素数是因子为1和本身, 如果数c不是素数,则还有其他因子,其中的因子,假如为a,b.其中必有一个大于sqrt© ,一个小于sqrt© 。所以m必有一个小于或等于其平方根的因数,故只验证到其方根即可),5,6测试点依然超时

#include <stdio.h>
#include <math.h>
int main(){
	int n, count = 0, flag;
	scanf("%d", &n);
	for(int i = 2; i <= n; i++){
		flag = 1;
		for(int j = 2; j <= sqrt(i); j++){
			if(i%j == 0){
				flag = 0;
				break;
			}
		}
		count += flag;
	}
	printf("%d", count);
	return 0;
}

埃氏筛法

  • 空间换时间
  • 因为一个合数一定能被分解为几个质数的幂的乘积,并且这个数的质因子一定是小于它本身的,所以当我们从小到大将每个质数的倍数都筛去的话,当遍历到一个合数时,它一定已经被它的质因子给筛去了。
    但是6测试点超时……
#include <stdio.h>
int hash[10000010] = {0};//初始为全是素数 
int main(){
	int n, count = 0;
	scanf("%d", &n);
	for(int i = 2; i <= n; i++){
		if(!hash[i]){
			count++;
			for(int j = 2 * i; j <= n; j += i)
				hash[j] = 1;
		}
	}
	printf("%d", count);
	return 0;
}

进一步优化,2 * 3我们已经判断过了,就没有必要再判断3 * 2了,因此从i*i开始判断即可
然鹅有时通过,有时测试点6超时……

#include <stdio.h>
const int N = 1e7 + 10;
int hash[N] = {0};//初始为全是素数 
int main(){
	long long n, count = 0;
	scanf("%lld", &n);
	for(long long i = 2; i <= n; i++){
		if(!hash[i]){
			count++;
			for(long long j = i * i; j <= n; j += i)
				hash[j] = 1;
		}
	}
	printf("%lld", count);
	return 0;
}

欧氏筛法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值