数论
拓展欧几里得(exgcd)
扩展欧几里得算法是在普通欧几里得算法(求最大公约数)的基础上,通过回溯过程记录系数,最终得到满足 \(ax + by = gcd(a, b)\) 的一组解 \((x,y)\)。核心逻辑是利用递归的思想,将大问题分解为小问题,直到递归边界 \((b=0)\),再反向推导系数。
int exgcd(int a,int b,int &x,int &y){
if(!b){
x=1,y=0;
return a;
}
int d=exgcd(b,a%b,y,x);
//d=exgcd(b,a%b,y,x)=b*y+(a-(a/b)*b)*x=a*x+b*(y-(a/b)*x)
y-=a/b*x;
return d;
}
欧拉函数
欧拉函数(Euler's totient function),即 \(\varphi(n)\),表示的是小于等于 \(n\) 和 \(n\) 互质的数的个数.当 \(n\) 是质数的时候,显然有 \(\varphi(n) = n - 1\).
性质:欧拉函数是积性函数,即对任意满足 \(\gcd(a, b) = 1\) 的整数 \(a,b\),有 \(\varphi(ab) = \varphi(a)\varphi(b)\).特别地,当 \(n\) 是奇数时 \(\varphi(2n) = \varphi(n)\).
普通求 \(phi\),时间复杂度 \(O(n\log n)\):
void Phi(int n){
for(int i=1;i<=n;i++) phi[i]=i;
for(int i=2;i<=n;i++){
if(phi[i]==i){
for(int j=i;j<=n;j+=i) phi[j]=phi[j]/i*(i-1);
}
}
}
线性筛求 \(phi\),时间复杂度 \(O(n)\):
void init(int n){
phi[1]=1;
for(int i=2;i<=n;i++){
if(!isprime[i]) primes[++cnt]=i,phi[i]=i-1;
for(int j=1;i*primes[j]<=n;j++){
isprime[i*primes[j]]=1;
if(i%primes[j]==0){
phi[i*primes[j]]=phi[i]*primes[j];
break;
}
phi[i*primes[j]]=phi[i]*phi[primes[j]];
}
}
}
扩展欧拉定理
费马小定理:设 \(p\) 是素数.对于任意整数 \(a\) 且 \(p\nmid a\),都成立 \(a^{p-1}\equiv 1\pmod p\).
欧拉定理:对于整数 \(m>0\) 和整数 \(a\),且 \(\gcd(a,m)=1\),有 \(a^{\varphi(m)}\equiv 1\pmod{m}\).
扩展欧拉定理
把欧拉定理推广到了底数与指数不互素的情形.
拓展中国剩余定理
中国剩余定理
中国剩余定理(Chinese Remainder Theorem, CRT) 可求解如下形式的一元线性同余方程组(其中 \(n_1, n_2, \cdots, n_k\) 两两互质):
过程
-
计算所有模数的积 \(n\);
-
对于第 \(i\) 个方程:
1.计算 \(m_i=\frac{n}{n_i}\);
2.计算 \(m_i\) 在模 \(n_i\) 意义下的 逆元 \(m_i^{-1}\);
3.计算 \(c_i=m_im_i^{-1}\)(不要对 \(n_i\) 取模).
- 方程组在模 \(n\) 意义下的唯一解为:\(x=\sum_{i=1}^k a_i\times c_i \pmod n\).
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=20;
ll a[N],b[N],x,y,ans;
ll ksm(ll a,ll b,ll p){
ll ans=0;
while(b){
if(b&1) ans=(ans+a)%p;
a=(a+a)%p;
b>>=1;
}
return ans;
}
ll exgcd(ll a,ll b){
if(!b){
x=1,y=0;
return a;
}
ll d=exgcd(b,a%b);
ll t=x;
x=y,y=t-a/b*y;
return d;
}
ll lcm(ll a,ll b){
return a*b/exgcd(a,b);
}
int main(){
int n;
ll M=1,m;
cin>>n;
for(int i=1;i<=n;i++){//x ≡ a[i] (mod b[i])
cin>>b[i]>>a[i];
M*=b[i];
}
for(int i=1;i<=n;i++){
m=M/b[i];
exgcd(m,b[i]);//计算 m 的逆元 (m*x+b[i]*y)%b[i]=1
for(int j=1;j<=a[i];j++) ans=((ans+m*x)%M+M)%M;
}
cout<<ans;
return 0;
}
扩展中国剩余定理
解决 \(n_1, n_2, \cdots, n_k\) 不满足两两互质时的同余方程组 .
1.考虑两个方程
这等价于:
其中 \((t_1, t_2)\) 是整数。
整理得:
2.解的存在条件
设 \(d=\gcd(m_1,m_2)\).
方程 \(m_1 t_1 \equiv a_2 - a_1 \ (\bmod\ m_2)\) 有解当且仅当 \(d \mid (a_2 - a_1)\)。
3. 合并为一个新方程
如果 \(d\mid(a_2-a_1)\),我们可以解这个同余方程:
两边除以 \(d\):
记 \(m_1' = \frac{m_1}{d},\ m_2' = \frac{m_2}{d}\),则 \(\gcd(m_1',m_2')=1\)。
解出
其中 \(k\) 是某个特解(用扩展欧几里得算法求得),\(t_1 = k + m_2' \cdot T\),\(T\) 是任意整数。
代回 \(x = a_1 + m_1 t_1\),于是:
4. 合并结果
令:
则解为:
这样我们把两个方程合并成了一个同余方程:
5. 算法步骤(n 个方程)
-
初始化:$ x = a_1,m = m_1$,即当前解为 \(x\equiv a_1 \ (\bmod\ m_1)\)
-
对于 $ i = 2 $ ~ $n $:
- 当前已知解为 $ x \equiv a \ (\bmod\ m) $,下一个方程 $ x \equiv a_i \ (\bmod\ m_i) $
- 即 $ x = a + m t $,代入第 \(i\) 个方程:\[a + m t \equiv a_i \ (\bmod\ m_i) \]\[m t \equiv a_i - a \ (\bmod\ m_i) \]
- 令 $ d = \gcd(m, m_i) $
- 如果 $ d \nmid (a_i - a) $,无解,结束
- 否则,解:\[\frac{m}{d} t \equiv \frac{a_i - a}{d} \ \left(\bmod\ \frac{m_i}{d}\right) \]
- 用扩展欧几里得求 $t \equiv k \ (\bmod \frac{m_i}{d}) $
- 更新:\[x \leftarrow a + m \cdot k \]\[m \leftarrow \mathrm{lcm}(m, m_i) = m \cdot (m_i / d) \](注意取模,让 $ x $ 保持在 $ [0, m) $ 内)
- 最终解为 $ x \ \bmod\ m $,最小非负解是 $ (x+m) \bmod m $。

浙公网安备 33010602011771号