素数筛
盗一波素数筛
const int mx = 1000000 + 1; ///在(1,mx)的范围内寻找素数
const int sqrt_mx = (int)sqrt((double)mx);
bool vis[mx];
int prime[mx / 10]; ///在mx>65000时建议写成 int prime[mx/10];
/*复杂度O(NloglogN)*/
void getPrime(int &cnt)
{
int i, j;
for (i = 2; i <= sqrt_mx; ++i)
if (!vis[i]) //不是合数
{
prime[cnt++] = i; //加进
for (j = i * i; j < mx; j += i) vis[j] = true;
}
for (; i < mx; ++i) if (!vis[i]) prime[cnt++] = i; //对于超过一半的都是素数
}
/*复杂度O(N),但常数比较大
O(N)是因为每个合数至多被赋true值一次(每个合数n仅在i=n的最大非平凡因子(不为1和n的因子)时被赋值)
以12为例,在原来的算法中,vis[12]在i=2和i=3时均被赋值为true
而在此算法中,vis[12]只在i=6时被赋值为true(6为12的最大非平凡因子)
*/
void linear_getPrime(int &cnt)
{
int i, j;
for (i = 2; i < mx; ++i)
{
if (!vis[i]) prime[cnt++] = i;
for (j = 0; j < cnt && i * prime[j] < mx; ++j)
{
vis[i * prime[j]] = true;
if (i % prime[j] == 0) break;
}
}
}