给定题目求 1~n的质数
1. 最蠢的办法
bool isprime(int n)
{
int k = n;
if (k == 1 || k == 0)return false;
for (int i = 2; i < k; i++)
{
if (k%i == 0)
return false;
}
return true;
}
这种方法应该只适合求比较小的数,当n为10000000时,那是相当费时间的。
2.普通方法
bool isprime(int n)
{
int k = sqrt(n);
if (k == 1 || k == 0)return false;
for (int i = 2; i <= k; i++)
{
if (k%i == 0)
return false;
}
return true;
}
因为是合数的话,就一定有一个小于sqrt(n)的因数(具体证明自行baidu),所以素数一定就没有。
虽然把n改成了sqrt(n)但是还是不够看啊,一般。
3.埃拉托斯特尼筛法
原理:核心就是素数的倍数不是素数,围绕这个思路来展开
:假设给定范围(a,b),我们从第一个素数2开始,删除所有2的倍数,直到2的倍数大于b时停止,然后从3的倍数开始删除,那现在轮到4了,但是4是2的倍数,所以4已经被删除了,所以跳到了5,一次类推,直到删的数是小于sqrt(b)的。
这里的表述有点变扭,毕竟也只是写给我自己看的,若是有人看到了,觉得不好也请见谅。
int* isprime=new int [100000001];//设定一个动态数组大一点
int a,b;
cin>>a>>b;
isprime[0]=isprime[1]=0;
for(int i=2;i<=b;i++)
isprime[i]=1;//先将范围内的所有数都标记为素数;
for(int i=2;i<=sqrt(b);i++)
{
if(isprime[i]==0)//如果这个数不是素数的话就continue
continue;
for(int j=i*i;j<=b;j+=i)
isprime[j]=0;//将合数全部标记为0;
}
这也就是代码的核心部分,具体是要输出所有素数,还是判断,自由发挥。
时间复杂度为:O(nloglogn)
4. 欧拉筛法
vis[1]=1;
for (int i=2;i<=n;i++)
{
if (!vis[i])
pri[++tot]=i;
for (int j=1;j<=tot;j++)
{
if (i*pri[j]>n) break;
vis[i*pri[j]]=1;
if (i%pri[j]==0) break;
}
}
这里的if (i%pri[j]==0) break;比较关键
看了别人那么多解释,我是这样理解的:
5.打表法
就是将数据都算出来,然后存起来,之后直接用就可以了。我是这么理解的