数论基础篇1
质数及其筛法
判断一个数是否是质数
可以直接枚举
[
2
,
n
−
1
]
[2,n-1]
[2,n−1] 中的每个数是否整除
n
n
n,如果有一个整除
n
n
n ,则这个数为合数,反之亦然。
其次,由于
n
n
n 的因子是成对出现的,即
i
∣
n
i|n
i∣n,那么
(
n
/
i
)
∣
n
(n/i)|n
(n/i)∣n,所以我们可以只枚举
[
2
,
n
]
[2,\sqrt{n}]
[2,n]
bool pd(int x){//返回1则为质数,0为合数
for(int i=2;i*i<=x;i++){
if(x%i==0)
return 0;
}
return 1;
}
判断[1,n]的质数
如果用上述方法,时间复杂度为 O ( n n ) O(n\sqrt{n}) O(nn),显然对于一些 n = 1 e 6 n=1e6 n=1e6的数据过不去,下面介绍两种更快的筛法
埃式筛法
我们找到一个质数 p p p,并将 1 ∗ p , 2 ∗ p ⋯ n ∗ p 1*p,2*p\cdots n*p 1∗p,2∗p⋯n∗p全部打上为合数的标记,那么最终剩下没打标记的就是质数,又因为每个数 n n n 最多有 l o g n logn logn个质因数,所以时间复杂度是 O ( n l o g n ) O(nlogn) O(nlogn)
bool vis[maxn];
int prime[maxn],cnt;
void sieve(int n){
for(int i=2;i<=n;i++){
if(!vis[i]){//是质数
prime[++cnt]=i;
for(int j=i*i;j<=n;j+=i)//因为2*i~(i-1)*i都被比i小的质数筛去
vis[j]=i;
}
}
}
欧拉筛法
我们发现上一种筛法来说重复筛了很多合数,所以这种算法是对上一种算法的优化,让每一个数只被筛一遍,所以这个算法规定只被最小的筛数筛掉
int prime[maxn],cnt;
bool vis[maxn];
void sieve(){
for(int i=2;i<maxn;i++){
if(!vis[i]){
prime[++cnt]=i;
}
for(int j=1;j<=cnt&&i*prime[j]<maxn;j++){
vis[prime[j]*i]=1;
if(i%prime[j]==0)
break;
}
}
}
这其中最重要的优化就是if(i%prime[j]==0) break;
,如果当前
i
i
i是扫到的质数的倍数,说明
p
r
i
m
e
[
j
+
1
]
prime[j+1]
prime[j+1]并不是
i
∗
p
r
i
m
e
[
j
+
1
]
i*prime[j+1]
i∗prime[j+1]的最小质因数。即
i
∗
p
r
i
m
e
[
j
+
1
]
i*prime[j+1]
i∗prime[j+1]的时候最小质因数为
p
r
i
m
e
[
j
]
prime[j]
prime[j]
最小公倍数和最大公因数
最大公因数
辗转相除法
先给结论:
g
c
d
(
a
,
b
)
=
g
c
d
(
b
,
a
%
b
)
gcd(a,b)=gcd(b,a\%b)
gcd(a,b)=gcd(b,a%b)
我们设
g
c
d
(
a
,
b
)
=
k
gcd(a,b)=k
gcd(a,b)=k
则
a
=
P
k
a=Pk
a=Pk
b
=
Q
k
b=Qk
b=Qk
a
%
b
=
(
P
%
Q
)
k
a\%b=(P\%Q)k
a%b=(P%Q)k
又因为
P
,
Q
P,Q
P,Q互质
所以
P
%
Q
与
Q
P\%Q与Q
P%Q与Q互质
所以
g
c
d
(
b
,
a
%
b
)
=
g
c
d
(
Q
k
,
(
P
%
Q
)
k
)
=
k
=
g
c
d
(
a
,
b
)
gcd(b,a\%b)=gcd(Qk,(P\%Q)k)=k=gcd(a,b)
gcd(b,a%b)=gcd(Qk,(P%Q)k)=k=gcd(a,b)
int gcd(int a,int b){
if(!b)
return a;
return gcd(b,a%b);
}
更相减损术
中国古代,九章算术中提到了一种求最大公约数的方法,即更相减损术.如果要对分式约分,如果
a
a
a,
b
b
b都是偶数,可以将
a
a
a,
b
b
b都折半;否则,将a和b交替地减去对方,直到最后两者相等,那么这个数(乘上原来除掉的2)为原来
a
a
a,
b
b
b的最大公约数.
其证明方法和辗转相除法差不多 即
a
%
b
=
a
−
k
∗
b
a\%b=a-k*b
a%b=a−k∗b
裴蜀定理
g
c
d
(
a
,
b
)
=
k
gcd(a,b)=k
gcd(a,b)=k且
k
∣
c
k|c
k∣c,则有
a
x
+
b
y
=
c
ax+by=c
ax+by=c
令
a
′
=
a
/
k
,
b
′
=
b
/
k
a'=a/k,b'=b/k
a′=a/k,b′=b/k,即若满足
a
′
x
+
b
′
y
=
=
1
a'x+b'y==1
a′x+b′y==1则裴蜀定理成立,其中
g
c
d
(
a
,
b
)
=
1
gcd(a,b)=1
gcd(a,b)=1
若
a
′
x
≡
1
a'x\equiv1
a′x≡1
(
m
o
d
(mod
(mod
b
)
b)
b),则裴蜀定理成立
引理一
内容:
a
∗
k
≡
0
a*k\equiv0
a∗k≡0
(
m
o
d
(mod
(mod
b
)
b)
b) 不成立.
其中
0
<
k
<
b
,
g
c
d
(
a
,
b
)
=
1
0<k<b,gcd(a,b)=1
0<k<b,gcd(a,b)=1
若
a
∗
k
%
b
=
=
0
a*k\%b==0
a∗k%b==0
因为
g
c
d
(
a
,
b
)
=
1
gcd(a,b)=1
gcd(a,b)=1
所以
k
%
b
=
=
0
k\%b==0
k%b==0
又因为
0
<
k
<
b
0<k<b
0<k<b
所以
k
%
b
≠
0
k\%b\ne0
k%b=0
所以引理一得正
推论
内容:若
g
c
d
(
a
,
b
)
=
1
gcd(a,b)=1
gcd(a,b)=1,则
0
,
a
,
2
∗
a
,
3
∗
a
…
(
b
−
1
)
∗
a
0,a,2*a,3*a\dots(b-1)*a
0,a,2∗a,3∗a…(b−1)∗a取模
b
b
b的余数各不相同
反正法:
假设
i
∗
a
,
j
∗
a
i*a,j*a
i∗a,j∗a取模
b
b
b的余数相同 则有
(
j
−
i
)
∗
a
%
b
=
0
(j-i)*a\%b=0
(j−i)∗a%b=0又因为
0
<
(
j
−
i
)
<
b
0<(j-i)<b
0<(j−i)<b,所以与引理一矛盾,故推论得证
引理2
内容: 若
g
c
d
(
a
,
b
)
=
1
gcd(a,b)=1
gcd(a,b)=1 则
a
∗
k
%
b
=
1
a*k\%b=1
a∗k%b=1其中
0
<
k
<
b
0<k<b
0<k<b
由推论易得
则裴蜀定理得证
费马定理
当
p
p
p为质数,且
a
%
p
!
=
0
a\%p!=0
a%p!=0 则有
a
p
−
1
%
p
=
1
a^{p-1}\%p=1
ap−1%p=1
1
∗
a
∗
2
∗
a
∗
…
(
p
−
1
)
∗
a
%
p
=
a
p
−
1
∗
(
p
−
1
)
!
%
p
1*a*2*a*\dots(p-1)*a\%p=a^{p-1}*(p-1)!\%p
1∗a∗2∗a∗…(p−1)∗a%p=ap−1∗(p−1)!%p
由裴蜀定理
1
∗
a
,
2
∗
a
…
(
p
−
1
)
∗
a
1*a,2*a\dots(p-1)*a
1∗a,2∗a…(p−1)∗a取模
p
p
p得集合为
[
1
,
p
−
1
]
[1,p-1]
[1,p−1]
所以
1
∗
a
∗
2
∗
a
∗
…
(
p
−
1
)
∗
a
%
p
=
(
p
−
1
)
!
%
p
1*a*2*a*\dots(p-1)*a\%p=(p-1)!\%p
1∗a∗2∗a∗…(p−1)∗a%p=(p−1)!%p
所以
a
p
−
1
%
p
=
1
a^{p-1}\%p=1
ap−1%p=1
同余等价类、剩余系、缩系
对于一个正整数 p p p,对于 a % p a\%p a%p,只可能有 p p p种结果,并且属于 [ 0 , p − 1 ] [0,p-1] [0,p−1]
模 p p p的剩余系记作 Z p Z_p Zp,即小于 p p p的所有非负整数
同余等价类,
考虑在模 p p p的剩余系下,只有 p p p种结果,所以每一个数都代表了 % p = a \%p=a %p=a的所有数,对于 a a a相同的数,我们称其为同余等价类
如果只考虑 g c d ( i , p ) = 1 gcd(i,p)=1 gcd(i,p)=1的元素,便得到一个子集,称这个子集为缩系,记作 Z p ∗ Z^*_p Zp∗
欧拉函数
ϕ
(
x
)
\phi(x)
ϕ(x)就是与
[
1
,
x
−
1
]
[1,x-1]
[1,x−1]中与
x
x
x互质的数的个数
欧拉函数就是缩系的大小
当
x
x
x为质数时,
ϕ
(
x
)
=
x
−
1
\phi(x)=x-1
ϕ(x)=x−1
当
x
x
x为
a
k
a^{k}
ak,其中
a
a
a为质数,则
ϕ
(
x
)
=
a
k
−
1
∗
(
a
−
1
)
=
a
k
∗
(
1
−
1
/
a
)
\phi(x)=a^{k-1}*(a-1)=a^{k}*(1-1/a)
ϕ(x)=ak−1∗(a−1)=ak∗(1−1/a)
当
x
=
a
1
k
1
∗
a
2
k
2
∗
⋯
∗
a
m
k
m
x=a_1^{k_1}*a_2^{k_2}*\dots*a_m^{k_m}
x=a1k1∗a2k2∗⋯∗amkm
又因为
ϕ
(
x
)
\phi(x)
ϕ(x)为积性函数(不展开证明不会)
所以
ϕ
(
x
)
=
ϕ
(
a
1
k
1
)
∗
ϕ
(
a
2
k
2
)
∗
⋯
∗
ϕ
(
a
m
k
m
)
\phi(x)=\phi(a_1^{k_1})*\phi(a_2^{k_2})*\dots*\phi(a_m^{k_m})
ϕ(x)=ϕ(a1k1)∗ϕ(a2k2)∗⋯∗ϕ(amkm)
=
a
1
k
1
∗
(
1
−
1
/
a
1
)
∗
a
2
k
2
∗
(
1
−
1
/
a
2
)
⋯
∗
a
m
k
m
∗
(
1
−
/
a
m
)
=a_1^{k_1}*(1-1/a_1)*a_2^{k_2}*(1-1/a_2)\dots*a_m^{k_m}*(1-/a_m)
=a1k1∗(1−1/a1)∗a2k2∗(1−1/a2)⋯∗amkm∗(1−/am)
=
x
∗
(
1
−
1
/
a
1
)
∗
(
1
−
1
/
a
2
)
∗
…
(
1
−
1
/
a
m
)
=x*(1-1/a_1)*(1-1/a_2)*\dots(1-1/a_m)
=x∗(1−1/a1)∗(1−1/a2)∗…(1−1/am)
求法
求一个数的欧拉函数
时间复杂度 O ( n ) O(\sqrt n) O(n)
int getphi(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>1)//有可能会有质因子大于sqrt(n)
ans=ans/x*(x-1);
return ans;
}
求 [ 1 , n ] [1,n] [1,n]所有数的欧拉函数
若用上面的方法,时间复杂度 O ( n l o g n ) O(nlogn) O(nlogn)
int phi[maxn];
void init(){
for(int i=2;i<maxn;i++){
if(!phi[i]){
phi[i]=i-1;
for(int j=i+i;j<maxn;j+=i){
if(phi[j]==0)
phi[j]=j;
phi[j]=phi[j]/i*(i-1);
}
}
}
}
欧拉定理
内容:如果
g
c
d
(
a
,
p
)
=
1
gcd(a,p)=1
gcd(a,p)=1 则有
a
ϕ
(
p
)
%
p
=
1
a^{\phi(p)}\%p=1
aϕ(p)%p=1
设集合
x
x
x 为模
p
p
p 意义的缩系,
m
m
m为集合
x
x
x的大小
x
1
∗
a
∗
x
2
∗
a
∗
⋯
∗
x
m
∗
a
%
p
=
x
1
∗
x
2
∗
⋯
∗
x
m
∗
a
m
x_1*a*x_2*a*\dots*x_m*a\%p=x_1*x_2*\dots*x_m*a^{m}
x1∗a∗x2∗a∗⋯∗xm∗a%p=x1∗x2∗⋯∗xm∗am
又因为
x
1
∗
a
,
x
2
∗
a
,
…
,
x
m
∗
a
x_1*a,x_2*a,\dots,x_m*a
x1∗a,x2∗a,…,xm∗a取模
p
p
p得到的集合还是缩系
所以
a
ϕ
(
p
)
=
1
a^{\phi(p)}=1
aϕ(p)=1
扩展欧拉定理
内容:
a
r
≡
a
r
%
ϕ
(
p
)
+
ϕ
(
p
)
a^r\equiv a^{r\%\phi(p)+\phi(p)}
ar≡ar%ϕ(p)+ϕ(p)
m
o
d
(
mod(
mod(
p
)
p)
p)
当且仅当
r
>
ϕ
(
p
)
r>\phi(p)
r>ϕ(p)
欧拉函数常用来降幂
逆元
定义
a
∗
b
%
p
=
1
a*b\%p=1
a∗b%p=1,则
b
b
b是
a
a
a的逆元
当且仅当
g
c
d
(
a
,
p
)
=
1
gcd(a,p)=1
gcd(a,p)=1
因为
a
p
−
1
≡
1
a^{p-1}\equiv1
ap−1≡1
所以
a
∗
a
p
−
2
≡
1
a*a^{p-2}\equiv 1
a∗ap−2≡1
所以
a
p
−
2
a^{p-2}
ap−2是
a
a
a的逆元
递推法
i n v [ i ] = ( ( p − p / i ) ∗ i n v [ p % i ] + p ) % m o inv[i]=((p-p/i)*inv[p\%i]+p)\%mo inv[i]=((p−p/i)∗inv[p%i]+p)%mo
扩展欧几里得
如何得到特殊解
这是用来解形如
a
x
+
b
y
=
c
ax+by=c
ax+by=c不定方程的,其中已知
a
,
b
,
c
a,b,c
a,b,c,且
g
c
d
(
a
,
b
)
∣
c
gcd(a,b)|c
gcd(a,b)∣c时此方程才有解,因为
a
x
,
b
y
ax,by
ax,by是
g
c
d
(
a
,
b
)
gcd(a,b)
gcd(a,b)的倍数,如果
c
c
c不是
g
c
d
(
a
,
b
)
gcd(a,b)
gcd(a,b)的倍数,则无解
若
g
c
d
(
a
,
b
)
∣
c
gcd(a,b)|c
gcd(a,b)∣c,我们把
a
,
b
,
c
a,b,c
a,b,c都除以
g
c
d
(
a
,
b
)
gcd(a,b)
gcd(a,b),
则变成了一个
a
′
x
+
b
′
y
=
c
a'x+b'y=c
a′x+b′y=c其中
g
c
d
(
a
′
,
b
′
)
=
1
gcd(a',b')=1
gcd(a′,b′)=1
即满足
a
′
x
≡
c
a'x\equiv c
a′x≡c在取模
b
′
b'
b′的意义下。
这变到了裴蜀定理的推理了,所以此时有解
我们可以解这个方程
a
x
+
b
y
=
g
c
d
(
a
,
b
)
ax+by=gcd(a,b)
ax+by=gcd(a,b),得到答案后再乘上
c
/
g
c
d
(
a
,
b
)
c/gcd(a,b)
c/gcd(a,b)
a
x
+
b
y
=
g
c
d
(
a
,
b
)
=
g
c
d
(
b
,
a
%
b
)
ax+by=gcd(a,b)=gcd(b,a\%b)
ax+by=gcd(a,b)=gcd(b,a%b)
设上式
=
b
x
′
+
(
a
%
b
)
y
′
=
b
x
′
+
(
a
−
a
/
b
∗
b
)
y
′
=bx'+(a\%b)y'=bx'+(a-a/b*b)y'
=bx′+(a%b)y′=bx′+(a−a/b∗b)y′
两边合并同类项
(
x
−
y
′
)
a
+
(
y
−
x
′
+
a
/
b
∗
y
′
)
b
=
0
(x-y')a+(y-x'+a/b*y')b=0
(x−y′)a+(y−x′+a/b∗y′)b=0
所以
x
=
y
′
x=y'
x=y′
y
=
x
′
−
a
/
b
∗
y
′
y=x'-a/b*y'
y=x′−a/b∗y′
这本质上是个递归过程
当当前这一层的
b
=
0
b=0
b=0则当前这一层的
x
=
0
,
y
=
1
x=0,y=1
x=0,y=1,然后向上回溯
void exgcd(int a,int b,int &gcd,int &x,int &y){
if(!b){
x=1,y=0,gcd=a;
return;
}
else{
exgcd(b,a%b,gcd,y,x);//因为x=y',不如交换位置
y-=x*(a/b);
}
}
通解
假设有
a
x
+
b
y
=
c
ax+by=c
ax+by=c和
a
x
1
+
b
y
1
=
c
ax_1+by_1=c
ax1+by1=c
则有
a
(
x
1
−
x
)
+
b
(
y
1
−
y
)
=
0
a(x_1-x)+b(y_1-y)=0
a(x1−x)+b(y1−y)=0
同除
g
c
d
(
a
,
b
)
gcd(a,b)
gcd(a,b)
则有
a
g
c
d
(
a
,
b
)
(
x
1
−
x
)
+
b
g
c
d
(
a
,
b
)
(
y
1
−
y
)
=
0
\frac{a}{gcd(a,b)}(x_1-x)+\frac{b}{gcd(a,b)}(y_1-y)=0
gcd(a,b)a(x1−x)+gcd(a,b)b(y1−y)=0
移项得到
a
g
c
d
(
a
,
b
)
(
x
1
−
x
)
=
−
b
g
c
d
(
a
,
b
)
(
y
1
−
y
)
\frac{a}{gcd(a,b)}(x_1-x)=-\frac{b}{gcd(a,b)}(y_1-y)
gcd(a,b)a(x1−x)=−gcd(a,b)b(y1−y)
因为
g
c
d
(
a
g
c
d
(
a
,
b
)
,
b
g
c
d
(
a
,
b
)
)
=
1
gcd(\frac{a}{gcd(a,b)},\frac{b}{gcd(a,b)})=1
gcd(gcd(a,b)a,gcd(a,b)b)=1
所以
b
g
c
d
(
a
,
b
)
∣
(
x
1
−
x
)
\frac{b}{gcd(a,b)}|(x_1-x)
gcd(a,b)b∣(x1−x)
得出
x
1
=
x
+
b
g
c
d
(
a
,
b
)
∗
t
x_1=x+\frac{b}{gcd(a,b)}*t
x1=x+gcd(a,b)b∗t 其中
t
t
t为任意整数
x
x
x的最小正整数解就是特殊解
x
%
b
g
c
d
(
a
,
b
)
x\%\frac{b}{gcd(a,b)}
x%gcd(a,b)b
中国剩余定理
中国剩余定理用于求解
{
x
≡
r
1
(
m
o
d
a
1
)
x
≡
r
2
(
m
o
d
a
2
)
…
x
≡
r
m
(
m
o
d
a
m
)
\begin{cases} x\equiv r_1 (mod\ a_1)\\ x\equiv r_2(mod\ a_2)\\ \dots \\ x\equiv r_m(mod\ a_m) \end{cases}
⎩⎪⎪⎪⎨⎪⎪⎪⎧x≡r1(mod a1)x≡r2(mod a2)…x≡rm(mod am)
其中
r
1
,
r
2
…
r
m
r_1,r_2 \dots r_m
r1,r2…rm互质
因为
r
1
,
r
2
…
r
m
r_1,r_2 \dots r_m
r1,r2…rm互质,所以我们设
A
i
=
∏
j
=
1
j
<
=
n
&
&
j
!
=
i
r
i
A_i=\prod_{j=1}^{j<=n\&\&j!=i}r_i
Ai=∏j=1j<=n&&j!=iri,此时
A
i
A_i
Ai与
r
i
r_i
ri互质,所以必定存在
c
i
c_i
ci使得
A
i
∗
c
i
%
r
i
=
1
A_i*c_i\%r_i=1
Ai∗ci%ri=1(由裴蜀定理的推理得出)。
可以推出
A
i
∗
c
i
−
r
i
∗
k
=
1
A_i*c_i-r_i*k=1
Ai∗ci−ri∗k=1
此时如果
g
c
d
(
A
i
,
r
i
)
=
=
1
gcd(A_i,r_i)==1
gcd(Ai,ri)==1,这个方程组才有解
然后用扩展欧几里得可以求出
c
i
c_i
ci
所以此时
x
i
x_i
xi=
A
i
∗
c
i
∗
a
i
A_i*c_i*a_i
Ai∗ci∗ai
最终答案
X
=
∑
i
=
1
i
<
=
m
x
i
X=\sum_{i=1}^{i<=m}x_i
X=∑i=1i<=mxi
因为
A
i
A_i
Ai为其他
r
j
r_j
rj的倍数,所以加起来并不影响答案的正确性
通解
X
=
X
+
k
∗
∏
i
=
1
i
<
=
n
r
i
X=X+k*\prod_{i=1}^{i<=n}r_i
X=X+k∗∏i=1i<=nri
void exgcd(int a,int b,int &gcd,int &x,int &y){
if(!b){
x=1,y=0,gcd=a;
return;
}
else{
exgcd(b,a%b,gcd,y,x);
y-=x*(a/b);
}
}
int r[maxn],a[maxn];
int CRT(){
int sum=1;
for(int i=1;i<=3;i++){
sum=sum*a[i];
}
int ans=0;
for(int i=1;i<=3;i++){
int gcd,x,y;
int now_m=sum/a[i];
exgcd(now_m,a[i],gcd,x,y);
ans=(ans+now_m*x%sum*r[i]%sum)%sum;
}
if(ans<0)
ans=ans+sum;
return ans;
}
扩展中国剩余定理
{
x
≡
r
1
(
m
o
d
a
1
)
x
≡
r
2
(
m
o
d
a
2
)
…
x
≡
r
m
(
m
o
d
a
m
)
\begin{cases} x\equiv r_1 (mod\ a_1)\\ x\equiv r_2(mod\ a_2)\\ \dots \\ x\equiv r_m(mod\ a_m) \end{cases}
⎩⎪⎪⎪⎨⎪⎪⎪⎧x≡r1(mod a1)x≡r2(mod a2)…x≡rm(mod am)
但是此时
r
1
,
r
2
,
…
,
r
m
r_1,r_2,\dots,r_m
r1,r2,…,rm并不互质
我们先取出前两个方程
{
x
≡
r
1
(
m
o
d
a
1
)
x
≡
r
2
(
m
o
d
a
2
)
\begin{cases} x\equiv r_1 (mod\ a_1)\\ x\equiv r_2(mod\ a_2)\\ \end{cases}
{x≡r1(mod a1)x≡r2(mod a2)
根据方程,我们可以得出
x
=
r
1
∗
k
1
+
a
1
x=r_1*k_1+a_1
x=r1∗k1+a1
x
=
r
2
∗
k
2
+
a
2
x=r_2*k_2+a_2
x=r2∗k2+a2
推出
r
1
∗
k
1
−
r
2
∗
k
2
=
a
1
−
a
2
r_1*k_1-r_2*k_2=a_1-a_2
r1∗k1−r2∗k2=a1−a2
你会发现这又是一个形如
a
x
+
b
y
=
c
ax+by=c
ax+by=c的方程
用扩展欧几里得便可以得到
k
1
k_1
k1的通解
k
1
=
k
1
+
t
∗
(
r
2
/
g
c
d
(
r
1
,
r
2
)
)
k_1=k_1+t*(r_2/gcd(r1,r2))
k1=k1+t∗(r2/gcd(r1,r2))
其中
t
t
t为任意实数
将
k
1
k_1
k1代入原式得到
x
=
r
1
∗
(
k
1
+
t
∗
(
r
2
/
g
c
d
(
r
1
,
r
2
)
)
+
a
1
x=r_1*(k1+t*(r_2/gcd(r1,r2))+a_1
x=r1∗(k1+t∗(r2/gcd(r1,r2))+a1
x
=
r
1
∗
k
1
+
t
∗
r
1
∗
r
2
/
g
c
d
(
r
1
,
r
2
)
+
a
1
x=r_1*k_1+t*r_1*r_2/gcd(r_1,r_2)+a_1
x=r1∗k1+t∗r1∗r2/gcd(r1,r2)+a1
x
=
r
1
∗
k
1
+
t
∗
l
c
m
(
r
1
,
r
2
)
+
a
1
x=r_1*k_1+t*lcm(r_1,r_2)+a_1
x=r1∗k1+t∗lcm(r1,r2)+a1
x
≡
r
1
∗
k
1
+
a
1
(
m
o
d
l
c
m
(
r
1
,
r
2
)
)
x\equiv r_1*k_1+a_1(mod\ lcm(r1,r2))
x≡r1∗k1+a1(mod lcm(r1,r2))
这便又是一个方程
这样我们便将两个方程变成一个方程
我们把这个方程再丢回去
方程组便少了一个
我们这样便可以求解
x
x
x
void exgcd(int a,int b,int &gcd,int &x,int &y){
if(!b){
x=1,y=0,gcd=a;
return;
}
else{
exgcd(b,a%b,gcd,y,x);
y-=x*(a/b);
}
}
int r[maxn],a[maxn];
int Fabs(int x){
if(x<0)
x=-x;
return x;
}
void exCRT(int n){
int gcd,x,y;
for(int i=1;i<n;i++){
exgcd(r[i],r[i+1],gcd,x,y);
if(Fabs(a[i+1]-a[i])%gcd!=0){
puts("-1");
return;
}
x=((x*(a[i+1]-a[i])/gcd)%(r[i+1]/gcd)+r[i+1]/gcd)%(r[i+1]/gcd);
int lcm=r[i]*r[i+1]/gcd;
r[i+1]=lcm;
a[i+1]=(x*r[i]+a[i])%lcm;
}
printf("%lld\n",a[n]);
}