【算法基础14】如何在最短的时间内判断一个数是不是质数?

一、试除法O(\sqrt{n}

1、判定质数

        主要思想:通过遍历除数看是否能够除尽。由于除数总是成对出现(例:6的除数是2和3),只要遍历到\frac{n}{i}即可。虽然由i=\frac{n}{i}可以推出i=\sqrt{n},但判断条件里写i=\sqrt{n}每次都要计算一遍\sqrt{n},增加时间开销;判断条件里写i*i=n当n比较大的时候i*i的结果可能存在溢出,影响条件判断。故在实际编程中的最优判断条件为i=n/i

        

bool is_prim(int n){
	if(n<=2) return true;
	for(int i=2;i<=n/i;i++){//注意循环判断条件
		if(n%i==0) return false;
	} 
	return true;
}

2、分解质因子

        主要思想:若n中存在两个大于\sqrt{n}的因子,则它们的乘积必定大于n,产生矛盾,故n中至多只有一个大于\sqrt{n}的因子,只要单独处理这种情况,我们就可以只循环n/i次,大大降低了计算时间。循环到第i次时,n已经不包含小于i的因子,故当n%i==0时,i也不包含小于i的因子,因此i必定是质数

void divide(int n){
	for(int i=2;i<=n/i;i++){//减少循环次数降低计算时间
		if(n%i==0){//找到n的因子,i必定是质数
			int s=0;
			while(n%i==0){
				n/=i;//去掉n中所有小于i的因子
				s++;
			}
			printf("%d %d\n",i,s);
		}		
	} 
	if(n>1) printf("%d %d\n",n,1);//最后剩下的是那个大于根号n的质因子
	puts("");
}

二、筛数法

1、埃氏筛数法O(nlog(logn))

        主要思想:从2开始遍历到n,将每次遍历数i的倍数都筛掉,最终剩下的全是质数。埃氏筛数法只需要筛掉质数的倍数,降低了计算时间。

void get_primes_A(int n){
	int cnt=0;
	for(int i=2;i<=n;i++){
		if(!st[i]){
			primes[cnt++]=i;//i是质数,加入集合	
			for(int j=i+i;j<=n;j+i) st[j]=true;//筛掉i的倍数
		} 
		
	}
}

2、线性筛数法O(n)

        主要思想:每个数都用它的最小质因子来筛除,确保了不会出现重复筛除的情况,将计算时间降低到线性。当i%primes[j]==0成立时,由于j是递增遍历,primes[j]一定是i的最小质因子,故也一定是primes[j]*i的最小质因子,后面的数再参与筛除将会造成重复筛的情况,跳出循环。

void get_primes_X(int n){
	int cnt=0;
	for(int i=2;i<=n;i++){
		if(!st[i]) primes[cnt++]=i;	
		for(int j=0;primes[j]<=n/i;j++){//注意循环判定条件
			st[primes[j]*i]=true;//由质数倒推它做最小质因子对应的数,筛掉
			if(i%primes[j]==0) break;//已经到此次筛除的最大限度,避免重复筛
		}		
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值