1 扩展欧几里得算法
扩展欧几里得算法主要可以解决:
·求乘法逆元
·求解同余方程/二元一次方程
其中,求乘法逆元可以转化成求解同余方程。
1.1求解方程 a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)的一组特解
先考虑以下二元一次方程:
a x + b y = g c d ( a , b ) ( 1 ) ax+by=gcd(a,b) \qquad\qquad\qquad\qquad\qquad\ \ \ (1) ax+by=gcd(a,b) (1)
b x ′ + ( a % b ) y ′ = g c d ( b , a % b ) = g c d ( a , b ) ( 2 ) bx'+(a\%b)y'=gcd(b,a\%b)=gcd(a,b) \qquad(2) bx′+(a%b)y′=gcd(b,a%b)=gcd(a,b)(2)
. . . ... ...
g c d ( a , b ) x ′ ′ + 0 ∗ y ′ ′ = g c d ( a , b ) ( 3 ) gcd(a,b)x''+0*y''=gcd(a,b)\qquad\qquad\ \ \ \ \ \ \ (3) gcd(a,b)x′′+0∗y′′=gcd(a,b) (3)
对于方程 ( 3 ) (3) (3),显然它的一个解是 x ′ ′ = 1 , y ′ ′ = 0 ; x''=1,y''=0; x′′=1,y′′=0;
想要求解方程 ( 1 ) (1) (1),我们就要找到方程 ( 1 ) ( 2 ) (1)(2) (1)(2)中 x , y x,y x,y与 x ′ , y ′ x',y' x′,y′之间的关系。
将方程 ( 2 ) (2) (2)变形:
b x ′ + ( a % b ) y ′ = g c d ( a , b ) bx'+(a\%b)y'=gcd(a,b) bx′+(a%b)y′=gcd(a,b)
b x ′ + ( a − ⌊ a / b ⌋ b ) y ′ = g c d ( a , b ) bx'+(a-\lfloor a/b \rfloor b)y'=gcd(a,b) bx′+(a−⌊a/b⌋b)y′=gcd(a,b)
将含 a a a和 b b b的项合并,得到
a y ′ + b [ ( x ′ − ⌊ a / b ⌋ ) y ′ ] = g c d ( a , b ) ( 4 ) ay'+b[(x'- \lfloor a/b \rfloor)y']=gcd(a,b)\ \ \ \ \ \ \ \ \ \ (4) ay′+b[(x′−⌊a/b⌋)y′]=gcd(a,b) (4)
将其与方程 ( 1 ) (1) (1)比较:
a x + b y = g c d ( a , b ) ( 1 ) ax+by=gcd(a,b) \qquad\qquad\qquad\qquad\ \ \ (1) ax+by=gcd(a,b) (1)
容易看出,可以取
x = y ′ x = y' x=y′
y = x ′ − ⌊ a / b ⌋ y ′ y = x'- \lfloor a/b \rfloor y' y=x′−⌊a/b⌋y′
作为方程 ( 1 ) (1) (1)的解。
因此,可以在递归调用欧几里得算法时不断更新 x x x和 y y y,得到方程的一组解。
C o d e : Code: Code:
void exgcd(int a,int b,int &x,int &y)
{
if(b == 0)
{
x = 1;
y = 0;
return;
}
exgcd(b,a%b,x,y);
int x_ = x;
x = y;
y = x_-a/b*y;
}
1.2求出二元一次方程 a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)的通解和最小正整数解
< < <结论 > > >设方程 a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)有特解 x = x 0 , y = y 0 x=x_0,y=y_0 x=x0,y=y0,
则方程 a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)通解形如
x = x 0 + t ∗ ( b / g c d ( a , b ) ) x=x_0+t*(b/gcd(a,b)) x=x0+t∗(b/gcd(a,b))
y = y 0 − t ∗ ( a / g c d ( a , b ) ) ( t ∈ Z ) y=y_0-t*(a/gcd(a,b))(t\in \mathbb{Z}) y=y0−t∗(a/gcd(a,b))(t∈Z),
最小正整数解 x m i n = ( x 0 + p ) % p . x_{min}=(x_0+p)\%p. xmin=(x0+p)%p.
< < <证明 > > >在 ( 1.1 ) (1.1) (1.1)中,我们解出了 a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)的一组通解 ( x 0 , y 0 ) (x_0,y_0) (x0,y0),设该方程的通解形如
x = x 0 + m x=x_0+m x=x0+m
y = y 0 + n y=y_0+n y=y0+n
代入方程得
a ( x 0 + m ) + b ( y 0 + n ) = g c d ( a , b ) = a x 0 + b y 0 a(x_0+m)+b(y_0+n)=gcd(a,b)=ax_0+by_0 a(x0+m)+b(y0+n)=gcd(a,b)=ax0+by0
a x 0 + a m + b y 0 + b n = a x 0 + b y 0 ax_0+am+by_0+bn=ax_0+by_0 ax0+am+by0+bn=ax0+by0
a m + b n = 0 am+bn=0 am+bn=0
a / b = − ( n / m ) = ( a / g c d ( a , b ) ) / ( b / ( g c d ( a , b ) ) ) a/b=-(n/m)=(a/gcd(a,b))/(b/(gcd(a,b))) a/b=−(n/m)=(a/gcd(a,b))/(b/(gcd(a,b)))
由于 a / g c d ( a , b ) a/gcd(a,b) a/gcd(a,b)和 b / g c d ( a , b ) b/gcd(a,b) b/gcd(a,b)一定互质(分数为最简分数),那么 m m m和 n n n一定是在这个分数基础上分子分母同乘一个整数 t t t得到的,因此一定有
m = t ∗ ( b / g c d ( a , b ) ) m=t*(b/gcd(a,b)) m=t∗(b/gcd(a,b))
n = ( − t ) ∗ ( a / g c d ( a , b ) ) n=(-t)*(a/gcd(a,b)) n=(−t)∗(a/gcd(a,b))
因此方程通解
x = x 0 + t ∗ ( b / g c d ( a , b ) ) x=x_0+t*(b/gcd(a,b)) x=x0+t∗(b/gcd(a,b))
y = y 0 − t ∗ ( a / g c d ( a , b ) ) y=y_0-t*(a/gcd(a,b)) y=y0−t∗(a/gcd(a,b))
t ∈ Z . t\in\mathbb{Z}. t∈Z.
若要求出最小正整数的 x m i n x_{min} xmin,记 b / g c d ( a , b ) = p b/gcd(a,b)=p b/gcd(a,b)=p,
当 x ≥ 0 x\geq0 x≥0时, x m i n = ( x 0 + t p ) % p = x % p x_{min}=(x_0+tp)\%p=x\%p xmin=(x0+tp)%p=x%p;
当 x < 0 x<0 x<0时, x m i n = ( x 0 + p ) % p . x_{min}=(x_0+p)\%p. xmin=(x0+p)%p.
1.3求出二元一次方程 a x + b y = c ax+by=c ax+by=c的特解
< < <结论 > > >若方程 a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)有特解 x = x 0 , y = y 0 x=x_0,y=y_0 x=x0,y=y0,
则方程 a x + b y = c ax+by=c ax+by=c当 c c c能被 g c d ( a , b ) gcd(a,b) gcd(a,b)整除时有特解
x = k x 0 x=kx_0 x=kx0
y = k y 0 , y=ky_0, y=ky0,
其中 k = c / g c d ( a , b ) k=c/gcd(a,b) k=c/gcd(a,b).
< < <证明 > > >通过上面 ( 1.1 ) (1.1) (1.1)的算法可以求解方程 a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)的一组解 ( x 0 , y 0 ) (x_0,y_0) (x0,y0),即
a x 0 + b y 0 = g c d ( a , b ) ax_0+by_0=gcd(a,b) ax0+by0=gcd(a,b)
设 c / g c d ( a , b ) = k c/gcd(a,b)=k c/gcd(a,b)=k(仅当 c c c被 g c d ( a , b ) gcd(a,b) gcd(a,b)整除,方程有解),于是
k ( a x 0 + b y 0 ) = k ⋅ g c d ( a , b ) k(ax_0+by_0)=k·gcd(a,b) k(ax0+by0)=k⋅gcd(a,b)
k a x 0 + k b y 0 = c kax_0+kby_0=c kax0+kby0=c
a ( k x 0 ) + b ( k y 0 ) = c a(kx_0)+b(ky_0)=c a(kx0)+b(ky0)=c
因此, x = k x 0 , y = k y 0 x=kx_0,y=ky_0 x=kx0,y=ky0是方程 a x + b y = c ax+by=c ax+by=c的一组特解。
1.4求出二元一次方程 a x + b y = c ax+by=c ax+by=c的通解
< < <结论 > > >若方程 a x + b y = c ax+by=c ax+by=c有特解 x = x 1 , y = y 1 x=x_1,y=y_1 x=x1,y=y1,
则方程 a x + b y = c ax+by=c ax+by=c有通解
x = x 1 + m ∗ ( b / g c d ( a , b ) ) x=x_1+m*(b/gcd(a,b)) x=x1+m∗(b/gcd(a,b))
y = y 1 − m ∗ ( a / g c d ( a , b ) ) , ( m ∈ Z ) . y=y_1-m*(a/gcd(a,b)),(m\in\mathbb{Z}). y=y1−m∗(a/gcd(a,b)),(m∈Z).
< < <证明 > > >记 a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)的一组特解为 x 1 , y 1 x_1,y_1 x1,y1,那么由 ( 1.3 ) (1.3) (1.3)中的推导可知, x = k x 1 , y = k y 1 x=kx_1,y=ky_1 x=kx1,y=ky1是方程 a x + b y = c ax+by=c ax+by=c的解。
假设方程有特解形如 x ′ = k x 1 + Δ x , y ′ = k y 1 + Δ y x'=kx_1+\Delta x,y'=ky_1+\Delta y x′=kx1+Δx,y′=ky1+Δy,
就有
a x ′ + b y ′ = a ( k x 1 + Δ x ) + b ( k y 1 + Δ y ) = c ax'+by'=a(kx_1+\Delta x)+b(ky_1+\Delta y)=c ax′+by′=a(kx1+Δx)+b(ky1+Δy)=c
a k x 1 + b k y 1 + a Δ x + b Δ y = c = a k x 1 + b k y 1 akx_1+bky_1+a\Delta x+b\Delta y=c=akx_1+bky_1 akx1+bky1+aΔx+bΔy=c=akx1+bky1
即 a Δ x + b Δ y = 0. a\Delta x+b\Delta y=0. aΔx+bΔy=0.
类似于 ( 1.2 ) (1.2) (1.2)中的过程,可得
a / b = − ( Δ y / Δ x ) = ( a / g c d ( a , b ) ) / ( b / g c d ( a , b ) ) a/b=-(\Delta y/\Delta x)=(a/gcd(a,b))/(b/gcd(a,b)) a/b=−(Δy/Δx)=(a/gcd(a,b))/(b/gcd(a,b))
因此
Δ x = m ∗ ( b / g c d ( a , b ) ) \Delta x=m*(b/gcd(a,b)) Δx=m∗(b/gcd(a,b))
Δ y = − m ∗ ( a / g c d ( a , b ) ) \Delta y=-m*(a/gcd(a,b)) Δy=−m∗(a/gcd(a,b))
所以 a x + b y = c ax+by=c ax+by=c的通解
x = k x 1 + Δ x = k x 1 + m ∗ ( b / g c d ( a , b ) ) x=kx_1+\Delta x=kx_1+m*(b/gcd(a,b)) x=kx1+Δx=kx1+m∗(b/gcd(a,b))
y = k y 1 + Δ y = k x 2 − m ∗ ( a / g c d ( a , b ) ) y=ky_1+\Delta y=kx_2-m*(a/gcd(a,b)) y=ky1+Δy=kx2−m∗(a/gcd(a,b))
m ∈ Z . m\in\mathbb{Z}. m∈Z.
1.5求乘法逆元
称一个数
a
a
a在模
p
(
g
c
d
(
a
,
p
)
=
1
)
p(gcd(a,p)=1)
p(gcd(a,p)=1)意义下的乘法逆元
x
x
x为满足条件
a
x
≡
1
(
m
o
d
p
)
ax \equiv 1 (mod\ p)
ax≡1(mod p)的一个
x
.
x.
x.
由同余的意义,可以将这个条件转化为
a x = k p + 1 ( k ∈ Z ) ax=kp+1(k\in \mathbb{Z}) ax=kp+1(k∈Z)
即 a x − k p = 1 ( g c d ( a , p ) = 1 ) ax-kp=1(gcd(a,p)=1) ax−kp=1(gcd(a,p)=1)
这时就转化为 ( 1.1 ) (1.1) (1.1)中方程 a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)当 g c d ( a , b ) = 1 gcd(a,b)=1 gcd(a,b)=1时的情况,就可以用扩展欧几里得算法求解了.然而求出的一个解 x 0 x_0 x0有可能为负值,如求解 5 5 5在模 13 13 13意义下的乘法逆元:
5 x − 13 k = 1 5x-13k=1 5x−13k=1
这时解 x = − 5 , k = − 2 x=-5,k=-2 x=−5,k=−2也成立。
而正确的乘法逆元为 8 8 8.此时对 x x x加上模数 13 13 13即可。
< < <证明 > > >若 a x 0 − k 0 p = 1 , − p < x 0 < 0 ( a , x 0 , k 0 , p ∈ Z ) ax_0-k_0p=1,-p\lt x_0 \lt 0(a,x_0,k_0,p\in\mathbb{Z}) ax0−k0p=1,−p<x0<0(a,x0,k0,p∈Z)则 x ′ = x 0 + p x'=x_0+p x′=x0+p是一个乘法逆元。
要证明 x ′ x' x′是一个 a a a的乘法逆元,只需要证明
a x ′ ≡ 1 ( m o d p ) ax'\equiv1(mod\ p) ax′≡1(mod p)
而 a x ′ = a ( x 0 + p ) = a x 0 + a p = k 0 p + 1 + a p = ( k 0 + a ) p + 1 ax'=a(x_0+p)=ax_0+ap=k_0p+1+ap=(k_0+a)p+1 ax′=a(x0+p)=ax0+ap=k0p+1+ap=(k0+a)p+1
即 a x ′ = ( k 0 + a ) p + 1 ax'=(k_0+a)p+1 ax′=(k0+a)p+1,两边同时取模得
a x ′ ≡ 1 ( m o d p ) . □ ax'\equiv1(mod\ p).\square ax′≡1(mod p).□
为了与 x ≥ 0 x\geq0 x≥0的情况统一,最终对 x x x进行 x = ( x + p ) % p x=(x+p)\%p x=(x+p)%p可确保得到一个 [ 0 , p − 1 ] [0,p-1] [0,p−1]的逆元。
C o d e : Code: Code:
int inv(int a,int mod)
{
int x,y;
exgcd(a,mod,x,y);
return (x+mod)%mod;
}
2 中国剩余定理(CRT)
《孙子算经》中记载了一个问题:“有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二。问物几何?”转化为数学语言为:
x ≡ 2 ( m o d 3 ) ( 1 ) x \equiv 2(mod\ 3)\qquad(1) x≡2(mod 3)(1)
x ≡ 3 ( m o d 5 ) ( 2 ) x \equiv 3(mod\ 5)\qquad(2) x≡3(mod 5)(2)
x ≡ 2 ( m o d 7 ) ( 3 ) x \equiv 2(mod\ 7)\qquad(3) x≡2(mod 7)(3)
求解 x x x。利用中国剩余定理可以解决这种问题模数之间互质的情况。(不互质可以用扩展中国剩余定理求解)
设上面三个方程的解分别为 x 1 , x 2 , x 3 x_1,x_2,x_3 x1,x2,x3,先考虑使 X = x 1 + x 2 + x 3 X=x_1+x_2+x_3 X=x1+x2+x3对于方程 ( 1 ) (1) (1)成立的条件:
若 x 2 , x 3 x_2,x_3 x2,x3均是 3 3 3的倍数,那么
X % 3 = ( x 1 + x 2 + x 3 ) % 3 = ( x 1 + 3 k 2 + 3 k 3 ) % 3 = x 1 % 3 = 2. X\%3=(x_1+x_2+x_3)\%3=(x_1+3k_2+3k_3)\%3=x_1\%3=2. X%3=(x1+x2+x3)%3=(x1+3k2+3k3)%3=x1%3=2.
这样,我们就找到了一个使 x 1 + x 2 + x 3 x_1+x_2+x_3 x1+x2+x3对方程 ( 1 ) (1) (1)成立的条件。
同时用方程 ( 2 ) ( 3 ) (2)(3) (2)(3)来限制 X = x 1 + x 2 + x 3 X=x_1+x_2+x_3 X=x1+x2+x3,可以得到:
x 1 x_1 x1是 5 5 5和 7 7 7的倍数;
x 2 x_2 x2是 3 3 3和 7 7 7的倍数;
x 3 x_3 x3是 3 3 3和 5 5 5的倍数.
那么,如果我们分别找到满足这些条件的一组 x 1 , x 2 , x 3 x_1,x_2,x_3 x1,x2,x3,由上面的推导可知, X = x 1 + x 2 + x 3 X=x_1+x_2+x_3 X=x1+x2+x3就是方程组 ( 1 ) ( 2 ) ( 3 ) (1)(2)(3) (1)(2)(3)的一个解。
这时利用乘法逆元,有:
x ⋅ i n v ( x , p ) ≡ 1 ( m o d p ) x·inv(x,p) \equiv 1 (mod\ p) x⋅inv(x,p)≡1(mod p)
其中 i n v ( x , p ) inv(x,p) inv(x,p)为 x x x在模 p p p意义下的乘法逆元。
代入 x = 5 ∗ 7 = 35 , x=5*7=35, x=5∗7=35,得:
35 ∗ i n v ( 35 , 3 ) ≡ 1 ( m o d 3 ) 35*inv(35,3) \equiv 1(mod\ 3) 35∗inv(35,3)≡1(mod 3)
等式两边同时乘以方程 ( 1 ) (1) (1)的余数 2 2 2,得:
35 ∗ i n v ( 35 , 3 ) ∗ 2 ≡ 2 ( m o d 3 ) 35*inv(35,3)*2\equiv2(mod\ 3) 35∗inv(35,3)∗2≡2(mod 3).
取 x 1 = 35 ∗ i n v ( 35 , 3 ) ∗ 2 x_1=35*inv(35,3)*2 x1=35∗inv(35,3)∗2即可, x 2 , x 3 x_2,x_3 x2,x3可用类似方法求出。
我们就取得了一个 X = x 1 + x 2 + x 3 X=x_1+x_2+x_3 X=x1+x2+x3满足方程组 ( 1 ) ( 2 ) ( 3 ) . (1)(2)(3). (1)(2)(3).
然而这个 X X X不一定是满足方程组最小的 x x x,如果要找出最小的 x x x只需要把 X X X对 3 ∗ 5 ∗ 7 = 105 3*5*7=105 3∗5∗7=105取余即可。
经过这个例子,我们可以总结出更一般的求解算法:
对于同余方程组
x ≡ b 1 ( m o d a 1 ) x\equiv b_1(mod\ a_1) x≡b1(mod a1)
x ≡ b 2 ( m o d a 2 ) x\equiv b_2(mod\ a_2) x≡b2(mod a2)
. . . ... ...
x ≡ b n ( m o d a n ) x\equiv b_n(mod\ a_n) x≡bn(mod an)
其中 a 1 , a 2 , . . . , a n a_1,a_2,...,a_n a1,a2,...,an互质。
记 P I = ∏ i = 1 n a i = a 1 a 2 . . . a n PI=\prod_{i=1}^{n}a_i=a_1a_2...a_n PI=∏i=1nai=a1a2...an,
那么可以取
x 1 = ( P I / a 1 ) ∗ i n v ( P I / a 1 , b 1 ) ∗ b 1 x_1=(PI/a_1)*inv(PI/a_1,b_1)*b_1 x1=(PI/a1)∗inv(PI/a1,b1)∗b1
x 2 = ( P I / a 2 ) ∗ i n v ( P I / a 2 , b 2 ) ∗ b 2 x_2=(PI/a_2)*inv(PI/a_2,b_2)*b_2 x2=(PI/a2)∗inv(PI/a2,b2)∗b2
. . . ... ...
x n = ( P I / a n ) ∗ i n v ( P I / a n , b n ) ∗ b n x_n=(PI/a_n)*inv(PI/a_n,b_n)*b_n xn=(PI/an)∗inv(PI/an,bn)∗bn
X = x 1 + x 2 + . . . + x n X=x_1+x_2+...+x_n X=x1+x2+...+xn
满足要求的最小 x m i n = X % P I x_{min}=X\%PI xmin=X%PI.
P1495 【模板】中国剩余定理(CRT)/曹冲养猪
C o d e : Code: Code:
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1E5+1;
typedef long long LL;
int n;
int a[MAXN],b[MAXN];
void exgcd(LL a,LL b,LL &x,LL &y)
{
if(b == 0)
{
x = 1;
y = 0;
return;
}
exgcd(b,a%b,x,y);
LL _x = x;
x = y;
y = _x-a/b*y;
}
LL inv(LL a,LL mod)
{
LL x,y;
exgcd(a,mod,x,y);
return (x%mod+mod)%mod;
}
LL add(LL a,LL b,LL MOD)
{
return (a%MOD+b%MOD)%MOD;
}
int main()
{
scanf("%d",&n);
LL PI = 1;
for(int i=1;i<=n;i++)
{
scanf("%d%d",a+i,b+i);
PI *= a[i];
}
LL sum = 0;
for(int i=1;i<=n;i++)
{
sum = add(sum , b[i]*inv(PI/a[i],a[i])*(PI/a[i]) , PI);
}
printf("%lld",sum);
return 0;
}
3 扩展中国剩余定理
当方程组
x ≡ b 1 ( m o d a 1 ) x\equiv b_1(mod\ a_1) x≡b1(mod a1)
x ≡ b 2 ( m o d a 2 ) x\equiv b_2(mod\ a_2) x≡b2(mod a2)
. . . ... ...
x ≡ b n ( m o d a n ) x\equiv b_n(mod\ a_n) x≡bn(mod an)
中的 a 1 , a 2 , . . . , a n a_1,a_2,...,a_n a1,a2,...,an不两两互质时,需要采用扩展中国剩余定理算法。
取出其中的两个方程:
x ≡ b 1 ( m o d a 1 ) x\equiv b_1(mod\ a_1) x≡b1(mod a1)
x ≡ b 2 ( m o d a 2 ) x\equiv b_2(mod\ a_2) x≡b2(mod a2)
由同余的意义,有
x = k 1 a 1 + b 1 x=k_1a_1+b_1 x=k1a1+b1
x = k 2 a 2 + b 2 x=k_2a_2+b_2 x=k2a2+b2
消去 x x x,得
k 1 a 1 + b 1 = k 2 a 2 + b 2 k_1a_1+b_1=k_2a_2+b_2 k1a1+b1=k2a2+b2
a 1 k 1 − k 2 a 2 = b 2 − b 1 a_1k_1-k_2a_2=b2-b1 a1k1−k2a2=b2−b1
为一个二元一次方程,可以用扩展欧几里得算法解出一个特解( ( 1.3 ) (1.3) (1.3)内容) ( k 1 , k 2 ) (k_1,k_2) (k1,k2)
由 ( 1.4 ) (1.4) (1.4)结论,方程组有通解
x = x 1 + m ∗ ( b / g c d ( a , b ) ) x=x_1+m*(b/gcd(a,b)) x=x1+m∗(b/gcd(a,b))
y = y 1 − m ∗ ( a / g c d ( a , b ) ) , ( m ∈ Z ) . y=y_1-m*(a/gcd(a,b)),(m\in\mathbb{Z}). y=y1−m∗(a/gcd(a,b)),(m∈Z).
又
x = ( k 1 + m r ) a 1 + b 1 , x=(k_1+mr)a_1+b_1, x=(k1+mr)a1+b1,其中 r = a 2 / g c d ( a 1 , a 2 ) r=a_2/gcd(a_1,a_2) r=a2/gcd(a1,a2)
所以
x = k 1 a 1 + m r a 1 + b 1 x=k_1a_1+mra_1+b_1 x=k1a1+mra1+b1
x = k 1 a 1 + m l c m ( a 1 , a 2 ) + b 1 x=k_1a_1+mlcm(a_1,a_2)+b_1 x=k1a1+mlcm(a1,a2)+b1
方程两边同模 l c m ( a 1 , a 2 ) lcm(a_1,a_2) lcm(a1,a2)得
x ≡ k 1 a 1 + b 1 ( m o d l c m ( a 1 , a 2 ) ) x\equiv k_1a_1+b_1(mod\ lcm(a_1,a_2)) x≡k1a1+b1(mod lcm(a1,a2))
这样,两个方程就合并成了一个方程,求解最后一个方程的最小正整数解即可。
P4777 【模板】扩展中国剩余定理(EXCRT)
C o d e : Code: Code:
#include<cstdio>
#include<cctype>
typedef __int128 LL;
const int MAXN = 1E5+1;
int n;
LL ai[MAXN],bi[MAXN];
inline void read(__int128 &X)
{
X = 0;
int w=0; char ch=0;
while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
if (w) X = -X;
}
void print(LL x)
{
if (!x) return ;
if (x < 0) putchar('-'),x = -x;
print(x / 10);
putchar(x % 10 + '0');
}
LL gcd(LL a,LL b)
{
return !b?a:gcd(b,a%b);
}
LL exgcd(LL a,LL b,LL &x,LL &y)
{
if(b == 0)
{
x = 1;
y = 0;
return a;
}
LL r = exgcd(b,a%b,x,y);
LL x_ = x;
x = y;
y = x_-a/b*y;
return r;
}
LL lcm(LL a,LL b)
{
return a*b/gcd(a,b);
}
LL solve(LL a,LL b,LL c)
{
LL x,y;
exgcd(a,b,x,y);
LL x1 = c/gcd(a,b)*x;
LL mod = b/gcd(a,b);
return (x1%mod+mod)%mod;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
read(ai[i]),read(bi[i]);
for(int i=1;i<n;i++)
{
LL a1 = ai[i],a2 = ai[i+1];
LL b1 = bi[i],b2 = bi[i+1];
LL k1 = solve(a1,a2,b2-b1);
ai[i+1] = lcm(a1,a2);
bi[i+1] = k1*a1+b1;
}
print(bi[n]);
return 0;
}
本博客为自己学习中的理解,如有错误还请指出。