avatar
fireworks99
keep hungry keep foolish

素数筛

筛法求素数

用筛法求素数的基本思想是:把从1开始的、某一范围内的正整数从小到大顺序排列, 1不是素数,首先把它筛掉。剩下的数中选择最小的数是素数,然后去掉它的倍数。依次类推,直到筛子为空时结束。

埃氏筛

void get_prime(long long n)
{
    tot = 0;
    memset(is, 1, sizeof(is));///bool类型数组全部初始化为1(默认全为质数)
    is[0] = is[1] = 0;///0、1不是质数,单列
    for(int i = 2; i <= n; ++i)///遍历数组
    {
        if(is[i])///若此数未被标为0,则其未被前面质数筛掉,属于质数,用它去筛后面的数
        {
            pri[++tot] = i;///(1)将此数存于质数数组            pri[0]里没存数字
            for(int j = i + i; j <= n; j += i)///(2)从其2倍开始筛
            {
                is[j] = 0;
            }
        }
    }
}

线性筛

每个合数仅被它的最小质因子筛过,且为一次

void prime(int n)
{
    tot = 0;
    memset(vis, 1, sizeof(vis));
    vis[0] = vis[1] = false;
    for (int i = 2; i <= n; i++)
    {
        if (vis[i])
            p[++tot] = i;
        for (int j = 1; j <= tot && p[j] * i <= n; j++)
        {
            vis[p[j]*i] = false;                          ///合数被他的最小质因子筛掉
            if (i % p[j] == 0)                            ///"只"
                break;
        }
    }
}

关于if(i % p[j] == 0)

其功能:保证每个数只被它最小的因子筛掉

其机理:

证明(反证):

假设 i = k * a(k 为常数、a为较小、较靠前的质数)

如果没有上面那句代码 ,ka % a == 0 了还去找下一个素数(a + x)去筛

首先筛掉 (a + x) k a 这个数字

我们发现那个数字的所有因子中,a 是比 (a + x)更小的

那就违背线性筛概念了,反证得这句代码很重要

//I'm not sure if we need this, but too scared to delete.

Site by Baole Zhao | Powered by Hexo | theme PreciousJoy