质数与约数
1.调和级数
- Proof(粗略计算):
- 更精确的公式:\[F(n)=\ln n+ \gamma+ \varepsilon n \]
- 其中:\[\gamma \approx0.57721 56649 01532 \]\[\varepsilon n \approx \dfrac{1}{2n} \]
2.质数个数
\(N\) 以内的质数个数:
也就是说,每 \(\ln N\) 个数中就可能出现一个质数。
则暴力寻找第一个比 \(x\) 大(小)的质数的时间复杂度为 \(O(\sqrt{x} \ln x)\),当 \(x\leq10^{14}\) 时可以在 \(1s\) 内跑过。
3.线性筛
void Solve(){
for(int i=2;i<=n;i++){
if(!vis[i]) prime.push_back(i);
for(int j:prime){
if(i>n/j) break;
vis[i*j]=1;
if(!i%j) break;
}
}
}
重点在:
if(!i%j) break;
这样就保证了每个合数都被它的最小质因子标记。
- Proof:
假设当前枚举到的数为 \(i\),其最小质因子为 \(v_i\)。尝试反证法。假设 \(j>v_i\),若尝试标记 \(i \times j\),则 \(i \times j\) 可以表示为 \(v_i \times \dfrac{i}{v_i} \times j\),此时不满足 "每个合数都被它的最小质因子标记"。
4.算术基本定理
其中:\(p_i\) 为质数,\(c_i\) 为常数,\(p_1<p_2<p_3<\dots<p_m\)。
由此可得,\(N\) 至多只有一个大于 \(\sqrt{N}\) 的质因子。
\(N\) 的约数个数:
\(N\) 的约数和:
从组合角度可以证明。
求 \(1 \sim N\) 的正约数集合:考虑用倍数法,枚举 \(i\) 作为约数,则 \(i,2i,3i,4i\dots\lfloor\dfrac{N}{i}\rfloor\) 的正约数集合中都含有 \(i\)。
int n;
vector<int> S[N];
void Solve(){
for(int i=1;i<=n;i++)
for(int j=1;i*j<=n;j++)
S[i*j].push_back(i);
for(int i=1;i<=n;i++){
for(int j:S[i])
printf("%d ",j);
puts("");
}
}
该算法的时间复杂度为 \(O(\sum_{i=1}^N \dfrac{N}{i})=O(N \log N)\)。
由此得到推论:\(1\sim N\) 的正约数集合大小之和不会超过 \(N \log N\)。
Ex.1 [P1463]反素数
- 引理 1:\([1,N]\) 中最大的反素数,就是 \([1,N]\) 中约数个数最多的数中的最小的一个。
- Proof:
用苦茶想 - 引理 2:对于 \(\forall i \in [1,N]\),不同的质因子个数不会超过 \(10\),所有质因子的指数之和不会超过 \(30\)。
- Proof:
计算器 yyds - 引理 3:设所有在 \([1,N]\) 中的反素数集合为 \(S\) 则对于 \(\forall k \in S\),有:\[k=\prod_{i=1}^mp_i^{c_i},c_1\geq c_2\geq c_3\geq \dots\geq c_m \]
- Proof:由引理 1 与 \(i \in [1,N]\) 得,把指数尽量加在较小质数上约数个数更大。
爆搜+剪枝可过,时间复杂度为 \(O(\text{玄学+可过})\)。
5.\(\gcd\) 与 \(\operatorname{lcm}\)
-
二者转化关系:
\[\operatorname{lcm}(a,b)=\dfrac{a\times b}{\gcd(a,b)} \] -
Proof:\(a=\gcd(a,b)\times k_1,b=\gcd(a,b)\times k_2\),可得 \(k_1 \perp k_2\),\(\operatorname{lcm}(a,b)=k_1\times k_2 \times gcd(a,b)=\dfrac{a\times b}{\gcd(a,b)}\)
-
更相减损术 \((a \geq b)\):
\[\gcd(a,b)=\gcd(a,a-b)=\gcd(b,a-b) \] -
Proof:以 \(\gcd(a,b)=\gcd(a,a-b)\) 为例。设 \(a,b\) 的公约数集合为 \(S_1\),\(a,a-b\) 的公约数集合为 \(S_2\)。对于 \(\forall k \in S_1\),\(a=k\times x_1,b=k\times x_2,a-b=k\times (x_1-x_2)\),则 \(S_1 \subseteq S_2\)。同理可得 \(S_2 \subseteq S_1 \Rightarrow S_1=S_2\),命题得证。
-
辗转相除法:
\[\gcd(a,b)=\gcd(b,a\bmod b) \] -
Proof:与更相减损术同理,令 \(a=pb+r \ (0 \le r <b)\),则 \(a \bmod b=r=a-pb\)。对于 \(\forall k \in S_1\),\(a=k\times x_1,b=k\times x_2,r=k\times (x_1-k_2\times p)\)。由此可得 \(S_1=S_2\)。
Ex.2 GCD 与 LCM
解法 1:
设 \(A=x_1\times GCD,B=x_2\times GCD\)。则 \(LCM=\dfrac{A\times B}{GCD}=x_1\times x_2\times GCD\)。考虑枚举 \(x_1\),则\(A=x_1\times GCD,B=\dfrac{LCM}{x_1}\)。当 \(x_1\) 合法时,显然有 \(x_1 \mid \dfrac{A}{GCD},\gcd(x_1,\dfrac{LCM}{GCD\times x_1})=1\)。
考虑 \(x_1\) 的枚举范围:
倒序枚举 \(x_1\),由于 \(x_1\) 越大,\(B-A\) 越小,则当找到第一个满足以上所有条件的 \(x_1\) 时停止枚举,此时答案为 \(\dfrac{LCM}{x_1}-x_1 \times GCD\)。
解法 2:
由于 \(x_1\times x_2=\dfrac{LCM}{GCD}\),则考虑将 \(\dfrac{LCM}{GCD}\) 分解质因数。设\(\dfrac{LCM}{GCD}=D\),由 \(\gcd(x_1,x_2)=1\) 得,\(x_1,x_2\) 不会有相同的质因子。则可以二进制枚举 \(D\) 的每一个质因子分给 \(x_1\) 还是 \(x_2\),答案取 min 即可。
Ex.3 Neko Does Maths
答案可表示为:
考虑枚举 \(a-b\) 的因子 \(w\) 作为分母,显然 \(k\) 越小答案越优。分两种情况讨论:
- 当 \(w \mid b\) 时,\(k\) 可以取 \(0\)。
- 否则,需要找到一个 \(k\),满足 \(w\mid (b+k)\)。易得 \(k=w- (b \bmod w)\)。
- 所有得到的 \(\operatorname{lcm}(a+k,b+k)\) 中的最小值即为答案。
6.整除分块
定义:对于 \(\forall i \in [1,n]\cup\mathbf{N_+}\),设 \(f(i)=\lfloor \dfrac{n}{i} \rfloor\),将所有 \(f(i)\) 相等的 \(i\) 分为一块。
向下取整性质:\(\lfloor \dfrac{n}{x} \rfloor = y \Rightarrow \lfloor \dfrac{n}{y} \rfloor=x \ (x\leq y)\)
- Proof:设 \(n=x \times y+r\ (0 \leq r < x)\),\(r\) 也满足 \(r \leq y\),可得 \(\lfloor \dfrac{n}{y} \rfloor=x\)。
定理:利用整除分块,总块数不会超过 \(2\sqrt{N}\)。
-
Proof:
设 \(x_1,x_2 \in [1,\sqrt{n}],x_2=x_1+1\)。设 \(y_1=\lfloor \dfrac{n}{x_1} \rfloor,y_2=\lfloor \dfrac{n}{x_2} \rfloor\),有 \(y1>y2\)。假设 \(y1=y2=k\geq\sqrt{n}\)。则有 \((0\leq c_1<x_1,0\leq c_2 <x_1+1)\):
\[\begin{aligned}x_1k+c_1&=(x_1+1)k+c_2\\x_1k+c_1&=x_1k+k+c_2\\c_1&=k+c_2\\k\geq \sqrt{n}&\Rightarrow c_1\geq\sqrt{n}\geq x_1\end{aligned} \]与 \(c_1<x_1\) 矛盾,假设不成立。则 \(y_1>y_2\) 得证。
-
对于 \(\forall i \in [y_2+1,y_1]\),\(f(i)=x_1\)。
取上界 \(y_1\) 时,\(\lfloor \dfrac{n}{y_1} \rfloor=x_1\)。
取下界 \(y_2+1\) 时:
- 则有 \(\lfloor \dfrac{n}{y2+1} \rfloor=x_1\)。
对于 \(\forall i \in [1,\sqrt{n}]\),\(f(i)\) 两两不同;
对于 \(\forall i \in [\sqrt{n},n]\),有连续一段的 \(f(i)\) 相同,且与 \([1,\sqrt{n}]\) 中的数字一一对应。
命题得证。
\(O(\sqrt{n})\) 求 \(\sum_{i=1}^n \lfloor\dfrac{n}{i}\rfloor\)
- 设一个块的左右端点为 \(L,R\),\(\lfloor \dfrac{n}{L} \rfloor=\lfloor\dfrac{n}{R} \rfloor = k\),则该块对答案的贡献为 \((R-L+1)k\)。\(L\) 即为上一个块的 \(R\) 加一,考虑如何 \(O(1)\) 求出某一个块的 \(R\)。
根据定义得,\(R\) 即为最大的使得 \(\lfloor \dfrac{n}{i} \rfloor =k\) 最大的 \(i\)。
把 \(n\) 表示为 \(kR+z\ (0\leq z<R)\),则 \(0 \leq z<k\)。
反证法:假设 \(z \geq k\),则 \(n=k(R+1)+z-k\),\(R\) 显然能被 \(R+1\) 替代,与 \(R\) 的定义矛盾。
由此可得 \(R=\lfloor \dfrac{n}{k}\rfloor=\bigg \lfloor \dfrac{n}{\lfloor \dfrac{n}{L} \rfloor} \bigg \rfloor\)。
ll DivBlock(){
ll res=0,j=0;
for(int i=1;i<=n;i=j+1){
j=n/(n/i);
res+=1ll*(j-i+1)*(n/i);
}
return res;
}
- 处理上界 \(n\) 与被除数 \(k\) 不相等:
ll DivBlock(){
ll res=0,j=0;
for(int i=1;i<=n;i=j+1){
if(k/i==0) break;
else j=min(k/(k/i),n);
res+=1ll*(k/i)*(j-i+1);
}
return res;
}
7.欧拉函数
定义与求法
定义:设 \(\phi(n)\) 为 \(n\) 的欧拉函数值,则:
也就是 \(1\sim n\) 之间与 \(n\) 互质的数字个数。
考虑如何快速求出这个式子。
根据算数基本定理,对 \(n\) 进行质因数分解,\(n=p_1^{c_1}\times p_2^{c_2}\times p_3^{c_3}\times \dots \times p_m^{c_m}\)。
假如 \(n\) 只有一个质因子 \(p\),则所有 \(1 \sim n\) 中 \(p\) 的倍数都不与 \(n\) 互质,可得 \(\phi(n)=n-\dfrac{n}{p}\)。
假如 \(n\) 还有一个质因子 \(q\),\(\phi(n)\) 还需要减去 \(\dfrac{n}{q}\),再加回被多减一次 \(p,q\) 共同的倍数个数 \(\dfrac{n}{pq}\) ,则:
推广到一般情况,可以推出:
特别地,\(\phi(1)=1\)。
从另外一个角度理解这个柿子:对于 \(n\) 的一个质因子 \(p\),\(p\) 的倍数在 \([1,n]\) 中的占比为 \(\dfrac{n}{\frac{n}{p}}=\dfrac{1}{p}\),则其余的数字占比为 \(1-\dfrac{1}{p}\)。对于所有与 \(n\) 互质的数字 \(i\),两者没有共同的质因子。则与 \(n\) 互质的数字占比为 \(\prod_\limits{i=1}^m(1-\dfrac{1}{p_i})\),乘上 \(n\) 即为 \(\phi(n)\) 的值。
\(\phi(n)\) 可以用质因数分解 \(O(\sqrt{n})\) 求出。
性质
-
对于 \(\forall n>1\),在 \([1,n]\) 之间与互质 \(n\) 的数字之和为 \(\dfrac{n\phi(n)}{2}\)。
- 对于 \(\forall i\) 满足 \(i \perp n\),\(\gcd(i,n)=\gcd(n-i,n)=1\)。也就是说,在 \([1,n]\) 之间与互质 \(n\) 的数字是成对出现的。由于上面的 \(i,n-i\) 的平均数为 \(\dfrac{n}{2}\),这些数字之和即为 \(\dfrac{n\phi(n)}{2}\)。
-
\(\phi(n)\) 是积性函数。
-
积性函数:若 \(a,b\) 互质,则 \(f(a)\times f(b)=f(ab)\)。
-
完全积性函数:对于 \(\forall a,b\in\mathbf{N_+}\),\(f(a)\times f(b)=f(ab)\)。
-
积性函数性质:对 \(n\) 进行唯一分解,\(n=\prod_\limits{i=1}^mp_i^{c_i}\),则有 \(f(n)=\prod_\limits{i=1}^m f(p_i)\)
-
性质 2 证明:由于 \(a,b\) 互质,则 \(a,b\) 没有共同的质因子。对 \(a,b\) 进行唯一分解得 \(a=\prod_\limits{i=1}^{m_1} p_i^{c_1},b=\prod_\limits{i=1}^{m_2}q_i^{c_i},ab=(\prod_\limits{i=1}^{m_1} p_i^{c_1})(\prod_\limits{i=1}^{m_2} q_i^{c_1})\) 。则有
\[\phi(ab)=ab[\prod_\limits{i=1}^{m_1}(\dfrac{p_i-1}{p_1})\prod_\limits{i=1}^{m_2}(\dfrac{q_i-1}{q_1})]=\phi(a)\phi(b) \]
-
-
设 \(n=p^k\)(\(p\) 是质数),则 \(\phi(n)=p^k-p^{k-1}=p^{k-1}(p-1)\)。
- 由于 \(n\) 只有 \(p\) 一个质因子,则 \(1\sim n\) 之间与 \(n\) 不互质的数必定是 \(p\) 的倍数,这样的数共有 \(\dfrac{n}{p}=\dfrac{p^k}{p}=p^{k-1}\) 个。由此可得 \(\phi(n)=n-p^{k-1}=p^k-p^{k-1}=p^{k-1}(p-1)\) 。
-
若 \(p\) 为质数,且 \(p\mid n\),则 \(\phi(np)=p\phi(n)\)。
- 容易得出,若对 \(n\) 与 \(np\) 分别做唯一分解,两个数的质因子集合相等。则有 \(\phi(np)=np\prod_\limits{i=1}^m(\dfrac{p_i-1}{p_i})=p\phi(n)\)。
-
若 \(p\) 为质数,且 \(p \nmid n\), 则 \(\phi(np)=(p-1)\phi(n)\)。
- 同样地,对 \(n\) 与 \(np\) 分别做唯一分解,\(np\) 的质因子集合比 \(n\) 的质因子集合多了一个 \(p\)。若 \(n=\prod_\limits{i=1}^m p_i^{c_i}\),则 \(\phi(np)=np(\prod_\limits{i=1}^m \dfrac{p_i-1}{p_i})\dfrac{p-1}{p}=\phi(n)(p-1)\)。
- 从另外一个角度考虑,\(p,n\) 一定是互质的,那么 \(\phi(np)=\phi(n)\phi(p)=\phi(n)(p-1)\)。
-
\(n=\sum_\limits{d\mid n}\phi(d)\),也就是 \(n\) 的所有约数的欧拉函数值之和为 \(n\)。
-
设 \(f(n)=\sum_\limits{d|n} \phi(d)\)。
-
设 \(n\perp m\),有 \(f(nm)=\sum_\limits{d\mid nm}\phi(d)\)。对 \(n,m,d\) 进行唯一分解,\(d\) 的质因子一部分来自于 \(n\),一部分来自于 \(m\),且两部分没有交集。则 \(\forall d=xy\),其中 \(x\mid n,y\mid m,x\perp y\)。由此进一步得到:
\[f(nm)=\sum_\limits{d\mid nm}\phi(d)=\sum_\limits{d\mid nm}\phi(x)\phi(y)=(\sum_\limits{d|n} \phi(d))(\sum_\limits{d|m} \phi(d))=f(n)f(m) \] -
则 \(f(n)\) 也为积性函数。根据积性函数的性质,对 \(n\) 进行唯一分解,\(f(n)=\prod_\limits{i=1}^m f(p_i^{c_i})\),而
\[f(p_i^k)=\sum_\limits{i=0}^k \phi(p_i)=1+\sum_\limits{i=1}^k (p^i-p^{i-1})=1-1+p-p+p^2-p^2+\dots+p^k=p^k \] -
\(f(n)=\prod_\limits{i=1}^m p_i^{c_i}=n\),得证。
-
线性求欧拉函数
根据性质 4 与性质 5,在线性筛的基础上稍加修改即可。
ll phi[N];
vector<int> prime;
bool vis[N];
void Solve(){
phi[1]=1;
for(int i=2;i<=n;i++){
if(!vis[i]){
prime.push_back(i);
phi[i]=i-1;
}
for(int j:prime){
if(i>n/j) break;
vis[i*j]=1;
if(i%j==0){
phi[i*j]=phi[i]*j;
break;
}
else phi[i*j]=phi[i]*(j-1);
}
}
}
Ex.4 GCD SUM
利用欧拉函数的性质化简柿子:
线性求出 \(1\sim n\) 的欧拉函数值即可计算。