几种素数筛法:朴素筛 埃氏筛 线性筛 代码 以及运行时间对比

之前在acm队训练的时候好像学了三种筛法现在只会朴素算法了。。
占个坑后面复习后补完,不然就白学了。。

突然想起来java的上下取整 开根号 绝对值 幂指函数 都不会,也在以后写在这吧 Math搞定一切

朴素算法

时间复杂度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)
                + " 毫秒完成。" );
	}
}
posted @ 2022-11-17 23:04  林动  阅读(67)  评论(0编辑  收藏  举报