浅析数论--埃氏筛/欧拉筛/杜教筛
\(\mathcal{0x01 绪论}\)
\(\mathcal{质数的判定试除法 or 六倍原理}\)
一个合数的约数总是成对出现的,如果$d|n$($d$能被$n$整除),那么$(n/d)|n$,因此我们判断一个数是否为质数的时候,
只需要判断较小的那一个数能否整除n就行了,即只需枚举$d<=(n/d)$,即$d<=n$,$d<=sqrt(n)$就行了。
为何不用$sqrt()$?请自行百度“$sqrt()$的运算方式”。你就会知道他是一个很慢的函数。
(1)试除法判断素数
bool is_prime(int x)
{
if (x < 2) return false;
for (int i = 2; i <= x / i; i ++ )//核心代码
if (x % i == 0)
return false;
return true;
}
(2)试除法分解质因数(唯一分解定理)
void divide(int x)
{
for (int i = 2; i <= x / i; i ++ )
if (x % i == 0)
{
int s = 0;
while (x % i == 0) x /= i, s ++ ;
cout << i << ' ' << s << endl;
}
if (x > 1) cout << x << ' ' << 1 << endl;
cout << endl;
}
(3)一个合数分解而成的质因数最多只包含一个大于$sqrt(n)$的质因数。
反证法,若$n$可以被分解成两个大于$sqrt(n)$的质因数,则这两个质因数相乘的结果大于$n$,与事实矛盾
(4)当枚举到某一个数$i$的时候,$n$的因子里面已经不包含$2-i-1$里面的数,
如果$n%i==0$,则$i$的因子里面也已经不包含$2-i-1$里面的数,因此每次枚举的数都是质数.
(5)算数基本定理(唯一分解定理):任何一个大于1的自然数$N$,如果$N$不为质数,那么$N$可以唯一分解成有限个质数的乘积
\(N=P1a1P2a2P3a3......Pnan\),这里$P1<P2<P3......<Pn$均为质数,其中指数$ai$是正整数。
这样的分解称为 \(N\) 的标准分解式。最早证明是由欧几里得给出的,由陈述证明。
此定理可推广至更一般的交换代数和代数数论。
(6)质因子(或质因数)在数论里是指能整除给定正整数的质数。根据算术基本定理,不考虑排列顺序的情况下,
每个正整数都能够以唯一的方式表示成它的质因数的乘积。
(7)两个没有共同质因子的正整数称为互质。因为$1$没有质因子,$1$与任何正整数(包括$1$本身)都是互质。
(8)只有一个质因子的正整数为质数。
\(\mathcal{筛质数}\)
\(\mathcal{朴素筛法}\)
(1)做法:把$2~(n-1)$中的所有的数的倍数都标记上,最后没有被标记的数就是质数.
(2)原理:假定有一个数$p$未被$2~(p-1)$中的数标记过,那么说明,不存在$2~(p-1)$中的任何一个数的倍数是$p$,也就是说$p$不是$2~(p-1)$中的任何数的倍数,也就是说$2~(p-1)$中不存在p的约数,因此,根据质数的定义可知:p是质数
(3)调和级数:当$n$趋近于正无穷的时候,\(1/2+1/3+1/4+1/5+…+1/n=lnn+c\).($c$是欧阳常数,约等于$0.577$左右.).
(4)底数越大,$log$数越小
(5)时间复杂度:约为$O(nlogn)$;(注:此处的$log$数特指以2为底的$log$数).
\(\mathcal{埃氏筛(稍加优化版的筛法)}\)
(1)质数定理:$1n$中有$n/lnn$个质数.
(2)原理:在朴素筛法的过程中只用质数项去筛.
(3)时间复杂度:粗略估计:\(O(n)\).实际:\(O(nlog(logn))\).
(4)$1n$中,只计算质数项的话,$"1/2+1/3+1/4+1/5+…+1/n"$的大小约为$log(logn)$.
\(\mathcal{线性筛}\)
(1)若$n$在$10$的$6$次方的话,线性筛和埃氏筛的时间效率差不多,若$n$在$10$的$7$次方的话,线性筛会比埃氏筛快了大概一倍.
(2)思考:一:线性筛法为什么是线性的?
二:线性筛法的原理是什么?
(3)核心:$1n$内的合数$p$只会被其最小质因子筛掉.
(4)原理:$1n$之内的任何一个合数一定会被筛掉,而且筛的时候只用最小质因子来筛,
然后每一个数都只有一个最小质因子,因此每个数都只会被筛一次,因此线性筛法是线性的.
(5)枚举到$i$的最小质因子的时候就会停下来,即if(i%primes[j]==0) break;
(6)因为从小到大枚举的所有质数,所以当i%primes[j]!=0时,primes[j]一定小于$i$的最小质因子,
primes[j]一定是primes[j]*i的最小质因子.
(7)因为是从小到大枚举的所有质数,所以当i%primes[j]==0时,primes[j]一定是$i$的最小质因子,
而primes[j]又是primes[j]的最小质因子,因此primes[j]是i*primes[j]的最小质因子.
(8)关于$for$循环的解释:
注:首先要把握住一个重点:我们枚举的时候是从小到大枚举的所有质数
1.当i%primes[j]==0时,因为是从小到大枚举的所有质数,所以primes[j]就是i的最小质因子,而primes[j]又是其本身
primes[j]的最小质因子,因此当i%primes[j]==0时,primes[j]是primes[j]i的最小质因子.
2.当i%primes[j]!=0时,因为是从小到大枚举的所有质数,且此时并没有出现过有质数满足i%primes[j]==0,
因此此时的primes[j]一定小于i的最小质因子,而primes[j]又是其本身primes[j]的最小质因子,
所以当i%primes[j]!=0时,primes[j]也是primes[j]i的最小质因子.
3.综合1,2得知,在内层$for$循环里面无论何时,primes[j]都是primes[j]i的最小质因子,因此st[primes[j]i]=true
语句就是用primes[j]i这个数的最小质因子来筛掉这个数.

浙公网安备 33010602011771号