之前在acm队训练的时候好像学了三种筛法现在只会朴素算法了。。
占个坑后面复习后补完,不然就白学了。。
Math搞定一切突然想起来java的上下取整 开根号 绝对值 幂指函数 都不会,也在以后写在这吧
朴素算法
时间复杂度O(n^1.5)
可以用来判断素数O(n^0.5),用来筛素数还是算了
static void get_p1(int n)
{
for(int i=2;i<=n;++i)
{
boolean flag=true;
for(int j=2;j<=Math.sqrt(i);++j)//开根号下取整没问题
{
if(i%j==0)flag=false;
}
if(flag)prime[cnt++]=i;
}
}
2022.2.4回来填坑
原来之前是学了3种,除了朴素算法用来判断素数,还有两种用来求N以内的素数,分别是埃氏筛和欧拉筛法(线性筛)
埃氏筛
时间复杂度o(nloglogn)
略,直接学线性筛
线性筛
时间复杂度o(n)
除了求N以内的素数还能求出N以内数的的最小质因子。
由于空间限制,N最大只能是在10^7以内的范围
static int prime[]=new int [N],cnt;
static int minp[]=new int [N];
static boolean st[]=new boolean [N];
static void get_prime(int n)
{
for(int i=2;i<=n;i++)
{
if(st[i]==false)
{
minp[i]=i;
prime[cnt++]=i;
}
for(int j=0;prime[j]*i<=n;++j)
{
int t=prime[j]*i;
st[t]=true;
minp[t]=prime[j];
if(i%prime[j]==0)break;
}
}
}
分解质因数:
int fact[]=new int [30];
int factnum[]=new int [30];
int k=0,tot=0;
while(x>1)
{
int p=minp[x];
fact[k]=p;factnum[k]=0;
while(x%p==0)
{
x/=p;
factnum[k]++;
tot++;
}
k++;
}
验证
10^5以内的素数有9592
10^6以内的素数有78498个
10^7以内的素数有664579个
对比
计算10^6以内素数对比
朴素筛法
线性筛法
计算10^7以内素数对比
朴素筛法
线性筛法
测试程序
import java.util.*;
public class Main
{
static int N=1<<20+5,n;
static int prime[]=new int [N],cnt;
static int minp[]=new int [N];
static boolean st[]=new boolean [N];
static void get_prime(int n)
{
for(int i=2;i<=n;i++)
{
if(st[i]==false)
{
minp[i]=i;
prime[cnt++]=i;
}
for(int j=0;prime[j]*i<=n;++j)
{
int t=prime[j]*i;
st[t]=true;
minp[t]=prime[j];
if(i%prime[j]==0)break;
}
}
}
static void get_prime2(int n)
{
for(int i=2;i<=n;++i)
{
boolean flag=true;
for(int j=2;j<=Math.sqrt(i);++j)//开根号下取整没问题
{
if(i%j==0)flag=false;
}
if(flag)prime[cnt++]=i;
}
}
public static void main(String args[])
{
Scanner sc=new Scanner(System.in);
n=sc.nextInt();
long startTime = new Date().getTime();
get_prime(n);
long endTime = new Date().getTime();
for(int i=0;i<cnt;++i)System.out.println(prime[i]);
System.out.println(cnt);
System.out.println("本程序运行 " + (endTime - startTime)
+ " 毫秒完成。" );
}
}