今天又回过头学习了素数的判断
才发现之前的简直不能看下去。果然,觉得编程这东西需要去及时复习,回顾,博客就是很不错的一个选择。今天就讨论下素数这东西的几种判断方法:
我们先定义变量: int i,m,N, isprime=1;
第一种:毫无思考可言,完全按照定义求:
用N来界定要求多少范围内的素数;
对于初学者而言,这没什么问题,但发挥各位聪明的小脑袋,稍微思考一下,有必要从2一直遍历到i-1吗?
答案是没有,当m走到m的1/2时其实就可以结束了,m能整除比它一半还大的数吗?显然,通过这步我们直接丢掉了一半的无用循环;
那么继续看根据数学推论,我们不用走到i/2;其实走到i的开平方就行,具体用sqrt()函数操作即可;(当然,这是数学推论,这里不予证明,感兴趣的话可以查查哦)还没完,我们再想,是不是有好多是没必要测的,没错,就是偶数,偶数一定是合数。所以,我们最外层循环这样写。
并且在判断的时候也可以减负;
是不是时间复杂度一下减少了好多倍。
别急,还没完。
一个合数必然可以由2个或多个质数相乘得到,那么如果一个数不能被比它一半还要小的素数整除,那么比它小一半的所有的合数也不可能整除它,素数是比较少的,是不是又优化了。
那么,问题来了,如何得到比它一半小的素数呢?
这就要用到新模式
先建立一个素数表,再拿素数表去测试它,素数表同样可以应用上述方法构造。
具体的如下面的代码:
//构建素数表
int array[10000]={2},i=3,m,isprime=1,cnt=1,N; / /2直接放在第一个位置,不用测
scanf("%d",&N);
for(i=3;i<=N;i+=2){
for(m=3;m<=sqrt(i);m+=2){
if(i%m==0){
isprime=0;
break;
}
}
if(isprime){
array[cnt]=i;
cnt++;
}
isprime=1;
} //构造结束
当然,这个方法对于超级大的数字有欠缺性,因为你做不出足够大的素数表去测试这个数。
对于超级大的数,可以先通过前几种方法先进行减负,然后用素数表判断。
这些高中知识就可以拿下,
当然还有更厉害的方法,例如费马小定理,
由于作者实力太菜,只能到这了。