素数定义:指在一个大于1的自然数中,除了1和此整数自身外,不能被其他自然数整除的数。
1,试除法
直接按照定义:
void getprime(int x)
{
for(int i=2;i<x;i++)
if(x%i==0) return false;
return true;
}
我们明显可以看出上面的这种方式有很多多余的判断,我们知道素数一定是奇数,所以只需要判断奇数是否能整除x就行了,为什么?因为奇数一定不能整除偶数。
void getprime(int x)
{
if(x%2==0&&x!=2) return false;
for(int i=3;i<x;i+=2)
if(x%i==0) return false;
return true;
}
是的,这中间还是有多余的判断,例如,100的因数有:1和100,2和50,4和25,5和20,10和10,我们可以看出因子都是成对出现的,其中2-sqrt(n)中间因子的数量为总因子数量的一半,也就是说只需要判断2-sqrt(n)中有没有x的因子就行了,如果2-sqrt(n)没有x的因子则2-n-1也没有。
void getprime(int x)
{
if(x%2==0&&x!=2) return false;
for(int i=3;i<=(int)sqrt(x);i+=2)
if(x%i==0) return false;
return true;
}
当然仍旧还是没完,我们看这个,判断101是否为素数,则整除的对象有:3,5,7,9我们看出如果x不能整除3则x一定也不能整除9,9是一个多余的判断,我们会发现被除数只需要是小于sqrt(x)的素数就行。
void getprime(int x)
{
for(inti=0;i<num&&prime[i]<=(int)sqrt(x);i++)
{
if(x%prime[i]==0) return false;
}
prime[num++]=x;
return true;
}
2,筛选法求素数
首先,2是公认最小的质数,所以,先把所有2的倍数去掉;然后剩下的那些大于2的数里面,最小的是3,所以3也是质数;然后把所有3的倍数都去掉,剩下的那些大于3的数里面,最小的是5,所以5也是质数......
上述过程不断重复,就可以把某个范围内的合数全都除去(就像被筛子筛掉一样),剩下的就是质数了。
void getprime()
{
fill(p,p+N,1);
for(int i=2;i<N;i++)
{
if(p[i])
{
for(int j=i+i;j<N;j+=i)
p[i]=0;
}
}
cnt=0;
for(int i=2;i<N;i++)
{
if(p[i])prime[cnt++]=i;
}
}
上面这个代码同样可以改进,在求解的同时记录素数
void getprime()
{
fill(p,p+N,1);
cnt=0;
for(int i=2;i<N;i++)
{
if(p[i]) prime[cnt++]=i;
for(int j=0;j<cnt&&prime[j]*i<N;j++)
{
p[prime[j]*i]=0;
if(i%prime[j]==0) break;
}
}
素数求解的一般方法就如上所述