这些零碎的知识点每个都学过N次了,但隔一段时间就会忘,记录下来
素数定义:只能被自身和1整除的大于1的正整数
通过这个定义,我们就可以得出判断素数的
- 第一种方法:
将这个素数除以从 (2,sqrt(n)] 的数,若没有整除的就是素数(这里所用的最大除数是sqrt(n)而不是n-1的原因是:现在正过来想,num1*num2 = n,那当试到num1>sqrt(n)的情况时,num2一定就<sqrt(n)那这种情况已经排除过了,就相当于重复计算)
这样时间复杂度是O(sqrt(n))
这里用到了cmath中的sqrt函数,其原型为double sqrt(double);
所以在取上界的时候,为了避免double带来的精度丢失,宁可多枚举一个也不能少一个,bound = (int)sqrt(n)+1;
bool isPrime(int x)
{
if(x<=1) return false;
int bound = (int)sqrt(x)+1;
for(int i = 2;i<=bound;i++)
{
if(x%i==0) return false;
}
return true;
}
但上述方法判断某个数是素数的复杂度还可以,但要是判断从1到n的所有数是否为素数,那就复杂度太高了O(n*sqrt(n))
- 第二种方法:
前面是得到某个数是素数就完了,没有充分利用这个信息
得到一个素数之后,就可以把求解范围内的所有是它倍数的数都去掉,当判断到某个数是不是素数的时候,已经把所有比它小的数的倍数都去掉了,那它一定是素数
#define maxn ...
bool isPrime[maxn];
void judge(void)
{
memset(isPrime,true,sizeof(isPrime));
isPrime[1] = false;
int bound = (int)sqrt(maxn)+1;
for(int i = 2;i<=bound;i++)
{
if(isPrime[i])
for(j = i;j*i<=maxn;j++) isPrime[j*i] = false; //并不需要从2*i就开始标记,因为k*i(k<i)一定在k的因数时就被标记过了
}
}
//把素数放在一个数组中,并且可以求有多少个
int prime[maxn];
int sum = 0;
for(int i = 1;i<=maxn;i++)
if(isPrime[i]) prime[sum++] = i;