T285368 入群条件(新生奶茶题)
本题考察的算法为素数筛
基本素数筛(埃氏筛)思想是:
给定一个素数数组,先假定除了0,1两个数之外的所有数全部都是素数
然后从2开始遍历到数组尾部,如果遍历到的数是素数,那么该数的倍数一定不是素数
int[] isprime = new int[1000005];//素数数组
Arrays.fill(isprime,1);//用1填满素数数组,表示全部都是素数
arr[0] = arr[1] = 0;
for(int i = 2; i < 1000005;i++){
for(int j = 2;i * j < 1000005;j++){
if(arr[i]==1){//如果i是素数
arr[i*j] = 0;//i的j倍数一定不为素数
}
}
}
这样我们就得到了一个素数数组,他的用法是arr[i] == 1 时表示i为素数,否则i不是素数
此素数筛预处理的时间复杂度为O(NloglogN)
但是对于本题,会超时
在数据接近1e7的时候,埃氏筛就会很慢,,此时就要用到更加快的筛法--线性筛
顾名思义,线性筛的时间复杂度是线性级,为O(N)
在埃氏筛中,30这个数被筛选了2*15 3*10 5*6三次,越往后,一个数被筛选的次数会越来越多,线性筛就是尽可能的减少被重复运算的次数
boolean[] arr = new boolean[10000005];
//素数数组
int[] prime = new int[1000005];
//用来存放第i个素数
int sum = 0;
Arrays.fill(arr, true);
arr[0] = false;
arr[1] = false;
//初始化
for (int i = 2; i < arr.length; i++) {
if (arr[i]) {
prime[++sum] = i;//是素数存入
}
for (int j = 1; j <= sum && i * prime[j] < arr.length; j++) {
arr[i * prime[j]] = false;//筛选倍数
if (i % prime[j] == 0) {// 避免重复运算
break;
}
}
}
如果不是很明白思路,可以自己人工充当一下计算机,运行一下代码
附上本题标程
Java:
import java.io.*;
import java.util.Arrays;
import java.util.StringTokenizer;
public class Main {
static class input {
BufferedReader brr = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer stk;
public String next() throws IOException {
while (stk == null || !stk.hasMoreTokens()) {
stk = new StringTokenizer(brr.readLine());
}
return stk.nextToken();
}
public int nextInt() throws IOException {
return Integer.parseInt(next());
}
public String readLine() throws IOException {
return brr.readLine();
}
}
public static void main(String[] args) throws IOException {
input read = new input();
long ans = 0;
int n = read.nextInt();
boolean[] arr = new boolean[10000005];
int[] prime = new int[1000005];
int sum = 0;
Arrays.fill(arr, true);
arr[0] = false;
arr[1] = false;
for (int i = 2; i < arr.length; i++) {
if (arr[i]) {
prime[++sum] = i;
}
for (int j = 1; j <= sum && i * prime[j] < arr.length; j++) {
arr[i * prime[j]] = false;
if (i % prime[j] == 0) {
break;
}
}
}
for (int i = 0; i <= n; i++) {
ans += prime[read.nextInt()];
}
System.out.println(ans);
}
}
c++:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e7;
int prime[N];
int arr[N];
int cnt = 0;
void init() {
for (int i = 2; i < N; i++) {
arr[i] = 1;
}
arr[1] = arr[0] = 0;
}
void fun() {
for (int i = 2; i < N; i++) {
if (arr[i]) prime[++cnt] = i;
for (int j = 1; j <= cnt && prime[j]*i < N; j++) {
arr[i * prime[j]] = 0;
if (i % prime[j] == 0) {
break;
}
}
}
}
int main() {
init();
fun();
int n,sum = 0;
cin >> n;
n++;
while(n--){
int i;
cin >> i;
sum += prime[i];
}
cout << sum;
return 0;
}