质数的概念:大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。
注:1即不是质数也不是合数
1.试除法判定质数
//判断一个数n是否是素数
bool isPrime(int n)
{
for(int i=2;i<=n/i;i++)
{
if(n%i==0)
return false;
}
return true;
}
2.朴素筛法求素数
int prim[N],cnt=0; //prim[]存储所有的素数
bool st[N]; //判断st[x]是否被筛掉
void get_Prime()
{
//循环里面需要做两件事
//1.如果i还没有被筛掉,那么i就是素数,并用prim数组来存储他。
//2.如果i的倍数小于等于N的话,将i的倍数都给筛掉
for(int i=2;i<=N;i++)
{
if(!st[i])//数字i还没有被筛掉的情况下,i就是素数
{
prim[cnt++]=i;
}
for(int j=i*i;j<=N;j+=i)
st[j]=true;
}
}
//通过以上函数,我们就得到了一张2-N的素数表
线性筛法求素数
- 任一大于1的自然数,要么本身是质数,要么可以分解为几个质数之积,且这种分解是唯一的。其中最小的质数称为该数的最小质因数。
int primes[N], cnt; // primes[]存储所有素数
bool st[N]; // st[x]存储x是否被筛掉
void get_primes(int n)
{
for (int i = 2; i <= n; i ++ )
{
if (!st[i]) primes[cnt ++ ] = i;
for (int j = 0; primes[j]*i <= n ; j ++ )
{
st[primes[j] * i] = true;
if (i % primes[j] == 0) break;
}
}
}
1.对于visit[i*prime[j]] = 1 的解释: 这里不是用i的倍数来消去合数,而是把 prime里面纪录的素数,升序来当做要消去合数的最小素因子。
2.对于 i%prime[j] == 0 就break的解释 :当 i是prime[j]的倍数时,i = kprime[j],如果继续运算 j+1,i * prime[j+1] = prime[j] * k prime[j+1],这里prime[j]是最小的素因子,当i = k * prime[j+1]时会重复,所以才跳出循环。
举个例子 :i = 8 ,j = 1,prime[j] = 2,如果不跳出循环,prime[j+1] = 3,8 * 3 = 2 * 4 * 3 = 2 * 12,在i = 12时会计算。因为欧拉筛法的原理便是通过最小素因子来消除。
试除法分解质因数:
void divide(int x)
{
for (int i = 2; i <= x / i; i ++ )
if (x % i == 0)
{
while (x % i == 0) x /= i, cout<<i<<' '; ;
}
if (x > 1) cout << x << ' ' << endl;
cout << endl;
}
eg:
给你两个整数L,R求区间[L,R]中相邻的两个质数的差值最大是多少(L,R<=2^31 ,R-L<=\(10^6\))
解析:
参考资料:
1.https://blog.csdn.net/qq_39763472/article/details/82428602