【编程马拉松算法目录>>>】
【001-NowCoder猜想】【工程下载>>>】
1 题目描述
nowcoder在家极度无聊,于是找了张纸开始统计素数的个数。设函数f(n)返回从1-n之间素数的个数。nowcoder 发现:
f(1) = 0
f(10) = 4
f(100) = 25
…
满足g(m) = 17 * m^2 / 3 - 22 * m / 3 + 5 / 3
其中m为n的位数。
他很激动,是不是自己发现了素数分布的规律了!
请你设计一个程序,求出f(n),来验证nowcoder是不是正确的,也许还可以得诺贝尔奖呢。^_^
1.1 输入描述:
输入包括多组数据。
每组数据仅有一个整数n (1≤n≤10000000)。
1.2 输出描述:
对于每组数据输入,输出一行,为1->n(包括n)之间的素数的个数。
1.3 输入例子:
1
10
65
100
0
1.4 输出例子:
0
4
18
25
2 解题思路
采用标记法求素数个数,假如输入是100,求100的平方根,得到10,再开辟大小为101的数组空间,将先将2倍数,但不包括2标记为非素数。现找下一个未标记的素数3,将3倍数,但不包括3标记为非素数。以此类推直到找到的素数大于10为止。最后统计未标记的数,那些数就是所求的素数。图2-1是以内的质数求解方法。
图2-1 100 以内的质数求解
3 算法实现
import java.util.Scanner;
/**
* Author: 王俊超
* Date: 2016-01-13 13:54
* CSDN: http://blog.csdn.net/derrantcm
* Github: https://github.com/Wang-Jun-Chao
* All Rights Reserved !!!
*/
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Scanner scanner = new Scanner(Main.class.getClassLoader().getResourceAsStream("data.txt"));
while (scanner.hasNext()) {
int n = scanner.nextInt();
if (n >= 1 && n <= 10_000_000) {
System.out.println(guess(n));
}
}
scanner.close();
}
/**
* 求[1, n]中素数的个数,使用标记法
*
* @param n 最大的范围
* @return 素数个数
*/
private static int guess(int n) {
// 标记是否是素数
// false表示是素数
// true表示不是素数
boolean[] mark = new boolean[n + 1];
mark[0] = true;
mark[1] = true;
// 标记质数
for (int i = 2; i < mark.length; i++) {
// i是质数
if (!mark[i]) {
for (int j = 2 * i; j < mark.length; j += i) {
mark[j] = true;
}
}
}
// 统计质数个数
int count = 0;
for (int i = 2; i < mark.length; i++) {
if (!mark[i]) {
count++;
}
}
return count;
}
}
4 测试结果
5 其它信息
因为markddow不好编辑,因此将文档的图片上传以供阅读。Pdf和Word文档可以在Github上进行【下载>>>】。