数论基础
声明
本文使用的字母 \(p\),默认是素数。
缺失证明:埃筛复杂度,欧拉函数积性性质,扩展欧拉定理。
小奥知识
- 素数与合数
- 同余
- 整除
- 约数与倍数
- 公约数与公倍数
- 互素
唯一分解定理
模运算
恒等式
用于化简带有模运算的式子。
龟速乘
将乘数二进制展开,类似于快速幂。
int mul(int a,int b){
int ans=0;
while(b){
if(b&1)ans=(ans+a)%p;
a=(a+a)%p,b>>=1;
}return ans;
}
相乘取模
直接用 __int128 就好了。
素数
素数计数函数
定义 \(\pi(x)\) 表示小于等于 \(x\) 的数中质数的个数,
随着 \(x\) 的增大,有 \(\pi(x) \approx \frac{n}{lnx}\)。
可用于计算与素数个数有关的算法的复杂度。
试除法
引理1:
显然。
那么我们就可以在 \(O(\sqrt{n})\) 的时间内判断一个质数。
bool check(int x){
if(x<2)return 0;
for(int i=2;i*i<=x;i++)
if(x%i==0)return 0;
return 1;
}
埃氏筛
用于找出小于 \(n\) 的所有质数。
若一个数 \(p\) 为质数,则将 \(n\) 以内所有 \(p\) 的倍数标记为合数。
显然,素数永远不会被筛掉,合数会被其所有质因子筛一遍。
复杂度为\(O(nlognlogn)\)
证明
还不会int prim[N],top;
bool vis[N];
for(int i=2;i<=n;i++){
if(!vis[i])prim[++top]=i;
else continue;
for(int j=i*2;j<=n;j+=i)vis[j]=1;
}
欧拉筛(线性筛)
考虑这样一件事:只要让每个合数只被筛一次,就能做到 \(O(n)\) 的复杂度。
算法流程:
若 \(i\) 未被筛到,则将 \(i\) 加入质数集合(有序);
每次 \(i\) 与质数集合中的数 \(p\) 相乘筛出合数,若 \(p|i\),则退出筛合数的集合。
int prim[N],top;
bool vis[N];
for(int i=2;i<=n;i++){
if(!vis[i])prim[++top]=i;
for(int j=1;j<=top&&prim[j]*i<=n;j++){
vis[prim[j]*i]=1;
if(i%prim[j]==0)break;
}
}
复杂度为\(O(n)\)
解释
结合上面的代码。设 \(i=p_1^{k_1}p_2^{k_2}...p_t^{k_t}\),
则 \(prim[j]\times i=p_1^{k_1}p_2^{k_2}...p_j^{k_j+1}...p_t^{k_t}\),
并且有 \(k_1=k_2=...=k_{j-1}=0\)。
于是我们知道:\(prim[j]\times i\) 被它最小的质因子筛掉,因而不会被筛掉第二次,保证了复杂度。
每一次都是将质数的指数增加的过程,故而每个合数都能被筛掉,保证了正确性。
欧拉函数
同余类 & 剩余系
同余类
对非零整数 \(m\),把全体整数分成 \(|m|\) 个两两不交的集合,且同一个集合中的任意两个数模 \(m\) 均同余,我们把这 \(|m|\) 个集合均称为模 \(m\) 的 同余类 或 剩余类。用 \(r\bmod m\) 表示含有整数 \(r\) 的模 \(m\) 的同余类。
不难证明对任意非零整数 \(m\),上述划分方案一定存在且唯一。
剩余系
对 \(m\) 个整数 \(a_1,a_2,\dots,a_m\),若对任意的数 \(x\),有且仅有一个数 \(a_i\) 使得 \(x\) 与 \(a_i\) 模 \(m\) 同余,则称这 \(m\) 个整数 \(a_1,a_2,\dots,a_m\) 为模 \(m\) 的 完全剩余系,简称 剩余系。
若无特殊说明,一般我们只用最小非负剩余系:\(\left \{ 0,1,2,\dots,m-1 \right \}\)
既约剩余类
对同余类 \(r\bmod m\),若 \((r,m)=1\),则称该同余类为 既约同余类 或 既约剩余类。
我们把模 \(m\) 既约剩余类的个数记作 \(\varphi(m)\),称其为 \(Euler\) 函数.
定义
定义 \(\varphi(x)\) 表示表示的是小于等于 \(n\) 和 \(n\) 互质的数的个数。
性质
- \(\varphi(p)=p-1\)
- \(\varphi(p^k)=(p-1)p^{k-1}\)
- 若 \(gcd(a,b)=1\),则\(\varphi(ab)=\varphi(a)\varphi(b)\),即欧拉函数为积性函数。
证明
- \(1\)~\(p-1\) 均与 \(p\) 互质。
- 仅有 \(p\) 的倍数与 \(p^k\) 不互质,\(p\) 的倍数共有 \(p^{k-1}\) 个,故 \(\varphi(p^k)=p^k-p^{k-1}\)。
- ???
公式
证明
设 \(n=p_1^{k_1}p_2^{k_2}\dots p_s^{k_s}\)
实现
短除法求 \(\varphi(x)\)
无需多言,套用公式即可。
时间复杂度为 \(O(\sqrt{n})\)。
int euler_phi(int x){
int ans=x;
for(int i=2;i*i<=x;i++)
if(x%i==0){ ans=ans/i*(i-1);
while(x%i==0)x/=i;
}
if(x>2)ans=ans/x*(x-1);
return ans;
}
线性求 \(\varphi(x)\)
分类讨论:
若 \(x\) 为素数,则\(\varphi(x)=x-1\);
若已知 \(\varphi(x)\) 与 \(\varphi(p)\),
若 \(p\) 为 \(x\) 的质因子,则 \(\varphi(px)=p\times x\prod^{}_{i\in P,i|x}\frac{i-1}{i}=p\times \varphi(x)\);
若 \(p\) 不为 \(x\) 的质因子,则 \(\varphi(px)=\varphi(x)\varphi(p)\)。
综上可以求出所有小于等于 \(n\) 的欧拉函数,用线性筛即可。
时间复杂度为 \(O(n)\)。
for(int i=2;i<=n;i++){
if(!vis[i])prim[++top]=i,phi[i]=i-1;
for(int j=1;j<=top&&prim[j]*i<=n;j++){
vis[prim[j]*i]=1;
if(i%prim[j]==0){ phi[prim[j]*i]=phi[i]*prim[j]; break; }
else phi[prim[j]*i]=phi[prim[j]]*phi[i];
}
}
线性求 \(\varphi(x!)\)
与上类似。
已知 \(\varphi((x-1)!)\),则 \(\varphi(x!)=\varphi((x-1)!\times x)\),
若 \(x\in P\),则 \(\varphi(x!)=\varphi((x-1)!\times x)=\varphi((x-1)!)\times \varphi(x)=\varphi((x-1)!)\times (x-1)\);
若 \(x\notin P\),则 \(\varphi(x!)=\varphi((x-1)!\times x)=x\times(x-1)!\prod^{}_{i\in P,i|(x-1)!}\frac{i-1}{i}=\varphi((x-1)!)\times x\)。
直接线性递推(可以套在线性筛里面)即可,时间复杂度为 \(O(n)\)。
fac_phi[1]=1;
for(int i=2;i<=n;i++){
if(!vis[i])prim[++top]=i,fac_phi[i]=fac_phi[i-1]*(i-1)%p;
else fac_phi[i]=fac_phi[i-1]*i%p;
for(int j=1;j<=top&&prim[j]*i<=n;j++){
vis[prim[j]*i]=1;
if(i%prim[j]==0)break;
}
}
欧拉定理 & 费马小定理
欧拉定理
证明
设 \(R=\left \{ r_1,r_2,r_3,\dots ,r_{\varphi(m)} \right \}\),其中 \(gcd(r_i,m)=1\) 且 \(r_i<m\)。
\(\because gcd(a,m)=1,gcd(r_i,m)=1\)
\(\therefore gcd(a\times r_i,m)=1\)
\(\therefore a\times r_i\bmod m \in R\)。
下证 \(a\times r_i\bmod m \ne a\times r_j\bmod m\):
假设存在,则有 \(a\times r_i\equiv a\times r_j(\bmod m)\),
那么 \(a\equiv 0(\bmod m)\) 或 \(r_i\equiv r_j(\bmod m)\),
显然都无解,故假设不成立,\(a\times r_i\bmod m\) 与 \(r_j\) 一一对应。
\(\Rightarrow r_1r_2r_3\dots r_{\varphi(m)}\equiv ar_1\times ar_2\times ar_3\dots \times ar_{\varphi(m)}\equiv a^{\varphi(m)}\times r_1r_2r_3\dots r_{\varphi(m)}(\bmod m)\)
\(\Rightarrow a^{\varphi(m)}\equiv 1(\bmod m)\),得证。
费马小定理
证明
特殊情况由欧拉定理可以直接得到。
另一种情况为 \(a|p\),显然 \(a^p\equiv 0^p\equiv 0(\bmod p)\)。
综上,得证。
扩展欧拉定理
证明
第一种情况:
第三种情况:
为避免分类,可以简化成这样的形式:
证明
欧几里得算法
辗转相减法 & 辗转相除法
更加本质的 \(gcd\) 与 \(lcm\)
设 \(a=p_1^{k_1}p_2^{k_2}p_3^{k_3}\dots\),\(b=p_1^{l_1}p_2^{l_2}p_3^{l_3}\dots\)。
则 \(gcd(a,b)=p_1^{min(k_1,l_1)}p_2^{min(k_2,l_2)}p_3^{min(k_3,l_3)}\dots\);
则 \(lcm(a,b)=p_1^{max(k_1,l_1)}p_2^{max(k_2,l_2)}p_3^{max(k_3,l_3)}\dots\)。
辗转相减法 & 辗转相除法
设 \(a>b\),则有 \(gcd(a,b)=gcd(a-b,b)=gcd(a-b,a)\)
显然,用上面的性质可以得到。
更进一步地,有 \(gcd(a,b)=gcd(a,b\bmod a)=gcd(a,a\bmod b)\)。
其实就是多次运用辗转相减法。
欧几里得算法
就是辗转相除法的代码实现:
int gcd(int a,int b){ return (!b)?a:gcd(b,a%b); }
复杂度为 \(O(logn)\)。
证明
不妨设 \(a>b\)。(\(a<b\) 的情况可以 \(O(1)\) 转化为 \(a>b\) 的情况)
若 \(a>2b\),则 \(a\bmod b\) 减小了至少一半。
若 \(a=2b\),则下一步即得出答案。
若 \(a<2b\),则 \(gcd(a,b)=gcd(b,a\bmod b)=gcd(b,a-b)\),
下一次递归即为 \(gcd(a-b,b\bmod(a-b))\)。
\(\because a<2b\),\(\therefore a-b<\frac{a}{2}\),减小至少一半。
综上可得复杂度为 \(O(logn)\)。
裴蜀定理
设 \(a,b\) 是不全为零的整数。那么,对于任意整数 \(x,y\),都有 \(\gcd(a,b)\mid ax+by\) 成立;而且,存在整数 \(x,y\),使得 \(ax+by=\gcd(a,b)\) 成立。
证明
1.\(\gcd(a,b)\mid ax+by\)
\(\because \gcd(a,b)|a\),\(\therefore \gcd(a,b)|ax\),\(\therefore \gcd(a,b)|ax+by\)。
2.\(ax+by=\gcd(a,b)\)
证明?扩欧算法直接构造答案!
设 \(s\) 为 \(ax+by\) 最小正整数解。
设 \(a=qs+r(0\le r<s)\)
即 \(r\) 亦满足 \(ax+by\) 的形式。
\(\because s\) 为最小正整数解,\(\therefore r=0\)。
\(\therefore s|a\),同理有 \(s|b\)。
\(\Rightarrow s|\gcd(a,b)\)。
又 \(\because \gcd(a,b)|s\),
\(\Rightarrow s=\gcd(a,b)\)
推论:存在整数 \(x,y\),使得 \(ax+by=k\gcd(a,b)\) 成立。
扩展欧几里得算法
在求 \(\gcd\) 的过程中,求出\(ax+by=\gcd(a,b)\) 的一组特解。
显然 \(ax+0y=\gcd(a,b)\) 有一组解为 \((1,0)\)。
现在已知 \(bx+(a\bmod b)y=\gcd(a,b)\) 的一组解为 \((x_0,y_0)\)。
有 \(ax+by=\gcd(a,b)\) 的一组解为 \((y_0,x_0-\left \lfloor \frac{a}{b} \right \rfloor \times y_0)\)。
证明
int Exgcd(int a,int b,int &x,int &y){
if(!b){ x=1,y=0; return a; }
int gcd=Exgcd(b,a%b,y,x);
y-=a/b*x; return gcd;
}
构造通解:
乘法逆元
定义
对于非零整数 \(a,m\),如果存在 \(b\) 使得 \(ab\equiv 1\pmod m\),就称 \(b\) 是 \(a\) 在模 \(m\) 意义下的 逆元。
将 \(b\) 记作 \(a^{-1}\)。
性质
乘法逆元用来解决除法问题。
- \(1^{-1}=1\)
- 逆元是唯一的。
- \(a^{-1}\) 的逆元为 \(a\)。
- \((ab)^{-1}=a^{-1}\times b^{-1}\)
2.证明
假设存在 \(x,y\),使得 \(ax\equiv ay\equiv 1\pmod m\)
那么 \(a\equiv 0\pmod m\) 或 \(x\equiv y\pmod m\),
显然都无解,故假设不成立。
费马小定理 & 欧拉定理
由欧拉定理及逆元的唯一性,知 \(a^{-1}=a^{\varphi(m)-1}\)。
特别地,若 \(m\in P\),有 \(a^{-1}=a^{m-2}\)。
快速幂求解,时间复杂度为 \(O(logn)\)。
扩展欧几里得算法
将线性同余方程 \(ax\equiv 1\pmod m\),
转化为 二元不定方程 \(ax+my=1\),求解即可。
复杂度为 \(O(logn)\)。
线性逆元
当 \(m\) 为素数时可用。
证明
设 \(m=ki+b,0\le b<i\)。
for(int i=2;i<=n;i++)
inv[i]=1ll*(p-p/i)*inv[p%i]%p;
阶乘逆元
阶乘的逆元等于逆元的阶乘。
fac[0]=inv[0]=fac_inv[0]=1;
fac[1]=inv[1]=fac_inv[1]=1;
for(int i=2;i<p;i++)
fac[i]=fac[i-1]*i%p,
inv[i]=(p-p/i)*inv[p%i]%p,
fac_inv[i]=fac_inv[i-1]*inv[i]%p;
用于求组合数。

浙公网安备 33010602011771号