素数判定

前言:应该说是很久前之前制定的打怪计划,但是由于各种原因迟迟没有开始动手,现在这里反思一下。。。


关于素数判定的基础知识:)

(1)素数判定有一个很基础很基础的写法,应该都知道的,就是求n以内的素数的时候,我们可以知道一个数i,它的因子数目一定是小于或等于sqrt(i)的,那么由此我们可以很简单的写出一段简短且简短且容易的代码:如下

#include<cstring>
#include<iostream>
#include<cmath> 
using namespace std;
const int maxn=10010;
int ss[maxn];
int main(){
	int n,i,j;
	scanf("%d",&n);
	int cnt=0;
	for(i=2;i<=n;i++){
	    for(j=2;j<=sqrt(i);j++)
	    	if(i%j==0)break;
	    	if(j>sqrt(i)) ss[cnt++]=i;
	}
	for(int k=0;k<cnt;k++)printf("%d ",ss[k]);
	return 0;
}
但是显然,复杂度是 o(n*sqrt(n)),数据一大,超时无疑(毫无意义!)。。此时nana陷入了苦恼(我能说我都差点忘了还有个主角吗。。TAT)我们接着往下走~

(2)不知道有没有听说过一种叫筛选法的东西,这是我们接下来要讲的求素数的东西:)

所谓筛选其实主要就是打素数表【划掉】就是说你可以开个bool型的数组来判断是否为素数,你可以过滤掉一些奇妙的东西(比如,一个素数小于n的倍数,显然这些数不是素数),那么代码也很简单了,如下:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<cmath> 
using namespace std;
const int maxn=10010;
int ss[maxn];
bool pd[maxn];
int main(){

	int n,cnt=0;
	scanf("%d",&n);
	pd[1]=0;
	for(int i=2;i<=n;i++)pd[i]=1;
	for(int i=2;i<=n;i++){
		if(pd[i]){
			ss[cnt++]=i;
			for(int j=2*i;j<=n;j+=i)pd[j]=0;
		}
	}
	for(int i=0;i<cnt;i++)printf("%d ",ss[i]);
	return 0;
}

 这种算法比上一种显然好了很多,但是这种算法有一个缺点: 只能打表不能单点判断(23333)如果(1)遇见不是小怪兽就会超时,那么这种也只是可以应付中等怪兽而已,终极大boss还是要更美妙的算法来KO

(3)以下的看起来特别厉害的东西,放心,不是我的【笑哭.jpg】某大大大神的东西,我在这里写下自己的想法:

有一个神奇的定理给了nana希望:“若正整数a>1,且a不能被不超过a的平方根的任一素数整除,则a是素数”

【证明还没写,我就不放了=W=】

由此,我们又发现了一个美妙代码,似乎可以help一下凹凸曼了:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<cmath> 
using namespace std;
const int maxn=10010;
int ss[maxn];
int cnt=0;
bool pd(int na){
	int ha=(int)sqrt(na);
	for(int i=0;ss[i]<=ha && cnt;i++){
		if(!(na%ss[i]))return false;
	}
	return true;
}
int main(){
	int n;
	scanf("%d",&n);
	for(int i=2;i<=n;i++){
		if(pd(i)) ss[cnt++]=i;
	}
	for(int i=0;i<cnt;i++)printf("%d ",ss[i]);
	return 0;
}

搭配定理一起食用就很容易了,不过它的劣势和筛选一样,只能打表。。。。。来来来,继续【捂脸.jpg】

(4)大神有提出了一种更好的算法用来单点判断,是由上面那种衍生来的,我再摘录一下【果然nana成神遥遥无期啊啊啊啊】

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<cmath> 
using namespace std;
int p[8]={4,2,4,2,4,6,2,6};
int pd(int n){
    if(n==1) return 0;
    if(n==2 || n==5 || n==3)return 1;
    if(n%2==0 || n%3==0 || n%5==0)return 0;
    int q=(int)sqrt(n);
    for(int i=7;i<=q;){
        for(int j=0;j<8;j++){
            if(n%i==0)return 0;
            i+=p[j];
        }
        if(n%i==0)return 0;
    }
    return 1;
}
int main(){
    int n;
    scanf("%d",&n);
    if(pd(n))puts("Yes");
    else puts("No");
    return 0;
}

其实也很好理解的。。


(5)关于欧拉函数的线性筛法,补充一下

基本就是两个定理组成的【某个符号显然不会打。。。。用ol代替。。】

1、ol(p)=p-1

2、if i%p==0 then ol(i*p)=p*ol(i)

证明比较多,书上和网上都有比较详细的解释,就不再赘述

啦啦啦,贴一发代码,错了的话。。。。【就打脸】

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<cmath> 
using namespace std;
const int maxn=10010;
int ss[maxn],ol[maxn];
int n;
bool pd[maxn];
int cnt=0;
void sss(){
	ol[1]=1;
	for(int i=2;i<=n;i++){
		if(!pd[i]){
			ol[i]=i-1;
			ss[cnt++]=i;
		}
		for(int j=0;j<cnt;j++){
			if(i*ss[j]>n)break;
			pd[i*ss[j]]=1;
			if(i%ss[j]==0){
				ol[i*ss[j]]=ol[i]*ss[j];
				break;
			}
			else{
				ol[i*ss[j]]=ol[i]*(ss[j]-1);
			}
		}
	}
}
int main(){
	scanf("%d",&n);
    sss();
    for(int i=0;i<cnt;i++)printf("%d ",ss[i]);
	return 0;
}




nana耗时好久暂时KO了素数判定的基础【可能不仅仅只有这些。。。。。】,可是魔仙女王的要求不仅仅只是如此,需要不断的雕刻雕刻,方能成一方美玉。

日子还长,我们慢慢走。





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值