模板 - 数学 - 数论 - 线性筛

线性筛质数,可以通过输出ptop之后调整p数组的大小。pm[i]表示i的最小质因子,pk[i]表示含有i的最小质因子的幂。其他的积性函数主要依靠pk的值来求解,比如现在枚举的是t,求出了他的最小质因子的幂pk[t],那么t/pk[t]与pk[t]显然是互质的。当t==pk[t]时,则t是p[j]的幂次,一般积性函数在质数的幂次都要特殊求解,不过欧拉函数和莫比乌斯函数可以直接从低一级的幂次转移过来。当t!=pk[t]时,直接分解成两个互质的数的乘积。要注意这个算法的空间消耗巨大。

const int MAXN = 1e7;
int p[MAXN + 5], ptop;
int pm[MAXN + 5], pk[MAXN + 5];

void sieve() {
    int n = MAXN;
    pm[1] = 1;
    pk[1] = 1;
    for(int i = 2; i <= n; i++) {
        if(!pm[i]) {
            p[++ptop] = i;
            pm[i] = i;
            pk[i] = i;
        }
        for(int j = 1; j <= ptop; j++) {
            int t = i * p[j];
            if(t > n)
                break;
            pm[t] = pm[p[j]];
            if(i % p[j]) {
                pk[t] = pk[p[j]];
            } else {
                pk[t] = pk[i] * p[j];
                break;
            }
        }
        //printf("i=%d pm=%d pk=%d\n", i, pm[i], pk[i]);
    }
    printf("ptop=%d\n",ptop);
    /*for(int i=1;i<=ptop;++i)
        printf("%d:%d\n",i,p[i]);*/
}

判断一个数是不是质数只需要判断pm[i]==i。判断一个数是不是质数的幂只需要判断pk[i]==i。当然1是奇异的,特殊处理就可以了。

很多时候只是需要质数,那么这样写比较省空间,也比较快。

const int MAXN = 1e7;
int p[MAXN + 5], ptop;
bool pn[MAXN + 5];

void sieve() {
    int n = MAXN;
    pn[1] = 1;
    for(int i = 2; i <= n; i++) {
        if(!pn[i])
            p[++ptop] = i;
        for(int j = 1; j <= ptop; j++) {
            int t = i * p[j];
            if(t > n)
                break;
            pn[t] = 1;
            if(i % p[j] == 0)
                break;
        }
    }
    printf("ptop=%d\n", ptop);
    /*for(int i = 1; i <= ptop; ++i)
        printf("%d:%d\n", i, p[i]);*/
}

猜你喜欢

转载自www.cnblogs.com/KisekiPurin2019/p/11969510.html