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

线性筛质数,可以通过输出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]时,直接分解成两个互质的数的乘积。要注意这个算法的空间消耗巨大。

1ex内的质数数量:

1e1|4
1e2|25
1e3|168
1e4|1229
1e5|9592
1e6|78498
1e7|664579
1e8|5761455

其他常见的上界:

2e5|17984
2e6|148933
2e7|1270607

5e5|41538
5e6|348513
5e7|3001134

第一个严格大于上界的最小质数连乘:
2*3*5 = 30 > 10 = 1e1
2*3*5*7 = 210 > 100 = 1e2
2*3*5*7*11 = 2310 > 1000 = 1e3
2*3*5*7*11*13 = 30030 > 10000 = 1e4
2*3*5*7*11*13*17 = 510510 > 100000 = 1e5
2*3*5*7*11*13*17*19 = 9699690 > 1000000 = 1e6
2*3*5*7*11*13*17*19*23 = 223092870 > 10000000 = 1e7

注意这个是严格大于,假如保证在上界以内的话事实上是少一个的。

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] = 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]);*/
}

原文地址:https://www.cnblogs.com/KisekiPurin2019/p/11969510.html

时间: 2024-11-09 19:21:37

模板 - 数学 - 数论 - 线性筛的相关文章

模板 - 数论 - 线性筛

各种线性筛的合集: https://www.cnblogs.com/zhoushuyu/p/8275530.html 常见积性函数: μ(n):莫比乌斯函数φ(n):欧拉函数d(n):一个数nn的约数个数σ(n):一个数nn的约数和f(x)=x^k(k∈N):这个玩意儿也是积性函数 线性筛素数 int pri[N],tot,zhi[N];//zhi[i]为1的表示不是质数 void sieve() { zhi[1]=1; for (int i=2;i<=n;i++) { if (!zhi[i])

数论线性筛总结 (素数筛,欧拉函数筛,莫比乌斯函数筛,前n个数的约数个数筛)

线性筛 线性筛在数论中起着至关重要的作用,可以大大降低求解一些问题的时间复杂度,使用线性筛有个前提(除了素数筛)所求函数必须是数论上定义的积性函数,即对于正整数n的一个算术函数 f(n),若f(1)=1,且当a,b互质时f(ab)=f(a)f(b),在数论上就称它为积性函数,若a,b不互质也满足的话则称作完全积性函数,下面说明每个筛子是怎么筛的. 最基础的是素数筛,其它三个筛都是以素数筛为前提 素数筛 void get_prime() { int pnum = 0; for(int i = 2;

【数论线性筛】洛谷P1865 A%B problem

题目背景 题目名称是吸引你点进来的 实际上该题还是很水的 题目描述 区间质数个数 输入输出格式 输入格式: 一行两个整数 询问次数n,范围m 接下来n行,每行两个整数 l,r 表示区间 输出格式: 对于每次询问输出个数 t,如l或r?[1,m]输出 Crossing the line 输入输出样例 输入样例#1: 2 5 1 3 2 6 输出样例#1: 2 Crossing the line 说明 [数据范围和约定] 对于20%的数据 1<=n<=10 1<=m<=10 对于100

模板 - 数学 - 数论 - 莫比乌斯反演 - 2

示例: 1.经典问题 求 $f(x,n,m)=\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}[gcd(i,j)==x]$ : 答案: $f(x,n,m) = \sum\limits_{k=1}\mu(k){\lfloor{\frac{n}{kx}}}\rfloor{\lfloor{\frac{m}{kx}}\rfloor}$ 构造: $F(x,n,m) = \sum\limits_{x|d}f(d) = \sum\limits_{k=1}f(kx) =\su

线性筛模板

蒟蒻要开始打数论模板了orz 线性筛都忘了怎么打,我太弱啦! #pragma GCC optimize("O2") #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<queue> #include<stack> #include<set> #in

洛谷 P3383 【模板】线性筛素数

P3383 [模板]线性筛素数 题目描述 如题,给定一个范围N,你需要处理M个某数字是否为质数的询问(每个数字均在范围1-N内) 输入输出格式 输入格式: 第一行包含两个正整数N.M,分别表示查询的范围和查询的个数. 接下来M行每行包含一个不小于1且不大于N的整数,即询问概数是否为质数. 输出格式: 输出包含M行,每行为Yes或No,即依次为每一个询问的结果. 输入输出样例 输入样例#1: 100 5 2 3 4 91 97 输出样例#1: Yes Yes No No Yes 说明 时空限制:5

P3383 【模板】线性筛素数

题目描述 如题,给定一个范围N,你需要处理M个某数字是否为质数的询问(每个数字均在范围1-N内) 输入输出格式 输入格式: 第一行包含两个正整数N.M,分别表示查询的范围和查询的个数. 接下来M行每行包含一个不小于1且不大于N的整数,即询问概数是否为质数. 输出格式: 输出包含M行,每行为Yes或No,即依次为每一个询问的结果. 输入输出样例 输入样例#1: 100 5 2 3 4 91 97 输出样例#1: Yes Yes No No Yes 说明 时空限制:500ms 128M 数据规模:

睡前数学一小时之线性筛素数:

睡前数学一小时之线性筛素数:1,朴素的筛素数算法:埃拉托斯特尼筛法.这是个简单再简单不过的一个素数的筛法.只是名字很拉风.这就告诉我们,往往东西不好这没什么,名字很拉风.别人也不会记住.hhhhh.这个的思路就是.每一个数都是由一个质数与和数(质数也可以)的积组成.这也是质数与和数的定义.而这个它这个筛发,就是当遇到一个质数的时候开始枚举,枚举[1,n]中间关于这个质数的倍数.每次都枚举,每次都将算出的这个数打上标记.而最后整个区间内的质数枚举完后,整个区间内的质数也就筛选出来了.这个很简单.时

数论入门——莫比乌斯函数,欧拉函数,狄利克雷卷积,线性筛,莫比乌斯反演,杜教筛

一个菜鸡对数论的一点点理解... 莫比乌斯函数 定义函数\(\mu(n)\)为: 当n有平方因子时,\(\mu(n)=0\). 当n没有平方因子时,\(\mu(n)=(-1)^{\omega(n)}\),\(\omega(n)\)表示n不同质因子的个数. 性质1: \(\sum_{d|n}\mu(d)=[n=1]\) 证明:我们把n分解质因数,则原式\(=(-1+1)^{\omega(n)}=0\). 因为对于不同的质因子,只有选和不选两种方案,这是一个组合数相加的形式,偶数加奇数减,根据二项式