理论是这个:https://blog.csdn.net/mush_me/article/details/106730956
这个是优化版本的
https://www.luogu.com.cn/record/34351152
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class Main {
//static int[] res;//=new int[100000009]; // 保存到这个位置的素数个数 不能开这么大, 内存限制只让128M ,因为中间的过程也不需要,所以不保存了
static boolean[] vis=new boolean[100000009]; //保存节点是否被访问后,访问过的都是合数
public static void main(String[] args) throws Exception{
BufferedReader reader =new BufferedReader(new InputStreamReader(System.in));
int N=Integer.parseInt(reader.readLine());
//int N=4974953; //346862
vis[1]=false;
int a=0;
int pa=0;
for (int x = 2; x <=N ; x++) { //从 x*x x*(x+1) ...x*(end)
if(vis[x] == false){//这是个素数,他的N倍都不是素数
for(int s=x;((long)s*x<=N);s++){//从 x*x x*(x+1) ... x*(N/x)
vis[s*x]=true;
}
a=pa+1;
pa=a;
}else{
a=pa;
}
}
System.out.println(a);
reader.close();
}
}
AC结果:https://www.luogu.com.cn/record/34351152
package info.frady.luogu;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class P3912H {
//static int[] res;//=new int[100000009]; // 保存到这个位置的素数个数 不能开这么大, 内存限制只让128M ,因为中间的过程也不需要,所以不保存了
static boolean[] vis=new boolean[100000009]; //保存节点是否被访问后,访问过的都是合数
public static void main(String[] args) throws Exception{
BufferedReader reader =new BufferedReader(new InputStreamReader(System.in));
//int N=Integer.parseInt(reader.readLine());
int N=4974953; //346862
vis[1]=false;
int a=0;
int pa=0;
for (int x = 2; x <=N ; x++) { //从 x*x x*(x+1) ...x*(end)
if(vis[x] == false){//这是个素数,他的N倍都不是素数
int end=N/x -x;
int axx=x*x;
int diff=-x;
for (int j = 0; j <= end ; j++) {// 只需要到 X*(N/X)
diff=diff+x;
int t=axx+diff;
vis[t]=true;
//vis[x * (x+j)]=true;
}
a=pa+1;
pa=a;
}else{
a=pa;
}
}
System.out.println(a);
reader.close();
}
}
一波简单的筛选
再提交了,就TL了,这是AC结果
https://www.luogu.com.cn/record/34348581
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class Main {
static boolean[] ahe=new boolean[100000009];//如果是合数,标记为true
public static void main(String[] args) throws Exception{
BufferedReader reader =new BufferedReader(new InputStreamReader(System.in));
int N=Integer.parseInt(reader.readLine());
//int N=4974953;
ahe[0]=true;
ahe[1]=true;
int cout=N-1;
for (int x = 2; x < N; x++) {//从 x*x x*(x+1) ...x*(end)
if(!ahe[x]){
int end=N/x -x;
for (int j = 0; j <= end ; j++) {
int t=x * (x+j);
if(!ahe[t]){
cout--;
}
ahe[ t ]=true;
}
}
}
/*int cout=0;
for (int i = 2; i <=N ; i++) {
if(!ahe[i]){
cout++;
}
}*/
System.out.println(cout);
reader.close();
}
}
后面又把乘法优化了一波,中午人多了,怎么改都没法AC了
package info.frady.luogu;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class P3912H {
static boolean[] ahe=new boolean[100000009];//如果是合数,标记为true
public static void main(String[] args) throws Exception{
BufferedReader reader =new BufferedReader(new InputStreamReader(System.in));
int N=Integer.parseInt(reader.readLine());
//int N=4974953;
ahe[0]=true;
ahe[1]=true;
int cout=N-1;
for (int x = 2; x < N; x++) {//从 x*x x*(x+1) ...x*(end)
if(!ahe[x]){// 如果不是合数,开筛选
int end=N/x -x;
int axx=x*x;
int diff=-x;
for (int j = 0; j <= end ; j++) {
diff=diff+x;
int t=axx+diff; //用这个优化,可以节省一点点时间,毕竟每次都乘,需要时间
if(!ahe[ t ]){//这个数是合数,那它就不是质数,质数的数量-1
cout--;
}
ahe[ t ]=true;
}
}
}
System.out.println(cout);
reader.close();
}
}