1.手动打表
当需要的数据范围较小时,比如下面的40个
int prime[40]={0,1,1,1,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,0,0,0,0,1,0,1,0,0,0,0,0,1,0,0};
//素数打表,因为n最大是20,所以只要打到40
2.按定义(耗时长)
最基本的方法是通过素数的定义直接判断,只能被1和它本身整除的数就是素数了。这种方法适合判断单个数是否为素数,当要求一个范围内素数而这个范围又比较大时,这种方法就不太使用了,甚至程序要运行几分钟才能算出结果。
int i,n,x;
while(scanf("%d",&n)!=EOF)
{
x=(int)sqrt(n);
for(i=2;i<=x;i++)
if(n%i==0) break;
if(i>x) printf("YES\n");
else printf("NO\n");
}
3.普通筛选法求素数
出现一个数,则把已这个数为因子的数都标记为合数。
如2,所以4,6,8 10....都标记为合数
如3,所以9,12,15.....都标记为合数
如4,所以16,20,24...都标记为合数
即,若i是素数,则从 j=i*i 开始,把 j+i , j+2i , j+3i .....都标记为合数 (因为2*i , 3*i,4*i,....(i-1)*i 分别是2,3,4,...i-1的的倍数,已经在i之前标记过,所以从j=i*i开始标记)
筛法的思想是去除要求范围内所有的合数,剩下的就是素数了,而任何合数都可以表示为素数的乘积,因此如果已知一个数为素数,则它的倍数都为合数。
int main()
{
int n=100;
int a[100000]={0};
int m=sqrt(n+0.5);
for(int i=2;i<=m;i++) if(!a[i])
for(int j=i+i;j<=n;j+=i) a[j]=1;
for(int i=2;i<=n;i++)
if(!a[i]) printf("%d ",i);
return 0;
}
版本二:
素数筛法是这样的:
1.开一个大的bool型数组prime[],大小就是n+1就可以了.先把所有的下标为奇数的标为true,下标为偶数的标为false.
2.然后:
for( i=3; i<=sqrt(n); i+=2 )
{ if(prime)
for( j=i+i; j<=n; j+=i ) prime[j]=false;
}
3.最后输出bool数组中的值为true的单元的下标,就是所求的n以内的素数了。
int prime[N];
int main()
{
int i, j;
for(i=2; i<N; i++)
{
if(i%2) prime[i]=1;
else prime[i]=0;
}
for(i=3; i<=sqrt(N); i++)
{
if(prime[i]==1)
for(j=i+i; j<N; j+=i)
prime[j]=0;
}
for(i=2; i<100; i++)//只输出2-100内的素数
if( prime[i]==1 )printf("%d ",i);
printf("\n");
return 0;
}
4.注意!!!!!!!
高效筛选法求素数(我是通过九九乘法表想通的(*^▽^*))
普通的线性筛法虽然大大缩短了求素数的时间,但是实际上还是做了许多重复运算,比如2*3=6,在素数2的时候筛选了一遍,在素数为3时又筛选了一遍。如果只筛选小于等于素数i的素数与i的乘积,既不会造成重复筛选,又不会遗漏。时间复杂度几乎是线性的。
/*
遇到素数需要打表时,先估算素数的个数:
num = n / lnx;
num为大概数字,越大误差越小(只是估计,用于估算素数表数组大小)
这个打表法效率貌似很高,网上说几乎达到了线性时间(不知道是真是假=。=)
*/
#include<iostream>
#include<string.h>
#include<stdio.h>
#include<stdlib.h>
#define maxn 10000000
bool visit[maxn+1000000];
int prime[maxn],n; ///prime的大小大概估计一下再开数组。大概是(x/lnx)
void getprime()
{
memset(visit, false, sizeof(visit));
int num = 0;
for (int i = 2; i <= n; ++i)
{
if ( !visit[i] ) prime[++num] = i;
for (int j = 1; j <= num && i * prime[j] <= n ; j++)
{
visit[ i * prime[j] ] = true;
if (i % prime[j] == 0) break; //此处是重点,避免了很多的重复判断,比如i=9,现在素数是2,3,5,7,进入二重循环,visit[2*9]=1;visit[3*9]=1;这个时候9%3==0,要跳出。因为5*9可以用3*15来代替,如果这个时候计算了,i=15的时候又会被重复计算一次,所以这里大量避免了重复运算。
}
}
}
int main()
{
scanf("%d",&n);
getprime();
return 0;
}