题意
求出一个 x i x_i xi满足 a i ∗ x i ≡ b i ( m o m i ) a_i*x_i\equiv b_i(mo m_i) ai∗xi≡bi(momi)
思路
( m ∣ x m|x m∣x表示 m m m是 x x x的因子,或者 x x x能被 m m m整除)
首先什么是同余 ?
设整数 m ≠ 0 m\neq0 m=0
若 m ∣ ( a − b ) m|(a-b) m∣(a−b),称 m m m位模数, a a a同余 b b b模 m m m, b b b是 a a a对模 m m m的剩余记作 a ≡ b ( m o d m ) a\equiv b(mod\ m) a≡b(mod m)
则我们可以知道
a
−
b
a-b
a−b是
m
m
m的倍数,因此上面的式子可以化为
a
∗
x
+
y
∗
m
=
b
\begin{aligned} &a*x+y*m=b\\ \end{aligned}
a∗x+y∗m=b
但是显然这里并不能使用 扩 展 欧 几 里 得 扩展欧几里得 扩展欧几里得
因为扩展欧几里得需要满足
a
∗
x
+
y
∗
m
=
g
c
d
(
a
,
m
)
\begin{aligned} &a*x+y*m=gcd(a,m)\\ \end{aligned}
a∗x+y∗m=gcd(a,m)
那么上面那个定理什么时候有解呢 ?
a
x
+
b
y
=
c
设
d
=
g
c
d
(
a
,
b
)
d
∣
a
,
d
∣
b
d
∣
(
a
x
)
,
d
∣
(
b
y
)
c
=
m
∗
d
=
m
∗
g
c
d
(
a
,
b
)
\begin{aligned} &\ \ \ ax+by=c\\ &设d=gcd(a,b)\\ &\ \ \ \ \ \ \ d|a,d|b\\ &\ \ \ d|(ax),d|(by)\\ &c=m*d=m*gcd(a,b) \end{aligned}
ax+by=c设d=gcd(a,b) d∣a,d∣b d∣(ax),d∣(by)c=m∗d=m∗gcd(a,b)
则显然
c
c
c是
g
c
d
(
a
,
b
)
gcd(a,b)
gcd(a,b)的时候有解,这就是贝祖定理
因此我们又回去考虑
a
∗
x
+
y
∗
m
=
b
\begin{aligned} &a*x+y*m=b\\ \end{aligned}
a∗x+y∗m=b
显然当 g c d ( a , m ) ∣ b gcd(a,m)|b gcd(a,m)∣b的时候有解
因此我们不妨先用扩展欧几里得求解出
a
∗
x
0
+
y
0
∗
m
=
g
c
d
(
a
,
m
)
\begin{aligned} &a*x_0+y_0*m=gcd(a,m)\\ \end{aligned}
a∗x0+y0∗m=gcd(a,m)
然后我们将式子左右两边同时乘上
b
g
c
d
(
a
,
m
)
\frac{b}{gcd(a,m)}
gcd(a,m)b
(
a
∗
x
0
+
y
0
∗
m
)
∗
b
g
c
d
(
a
,
m
)
=
g
c
d
(
a
,
m
)
∗
b
g
c
d
(
a
,
m
)
a
∗
x
0
∗
b
g
c
d
(
a
,
m
)
+
y
0
∗
b
g
c
d
(
a
,
m
)
=
b
\begin{aligned} &(a*x_0+y_0*m)*\frac{b}{gcd(a,m)}=gcd(a,m)*\frac{b}{gcd(a,m)}\\ &a*x_0*\frac{b}{gcd(a,m)}+y_0*\frac{b}{gcd(a,m)}=b \end{aligned}
(a∗x0+y0∗m)∗gcd(a,m)b=gcd(a,m)∗gcd(a,m)ba∗x0∗gcd(a,m)b+y0∗gcd(a,m)b=b
因此最后对于上面由扩展欧几里得求出的 x 0 x_0 x0 可以用来推导出所求式的 x x x
x = x 0 ∗ g c d ( a , m ) / b % m x = x_0*gcd(a,m)/b\%m x=x0∗gcd(a,m)/b%m
Code :
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
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);
y -= a / b * x;
return d;
}
int main()
{
int n;
scanf("%d", &n);
while (n -- )
{
int a, b, m;
scanf("%d%d%d", &a, &b, &m);
int x, y;
int d = exgcd(a, m, x, y);
if (b % d) puts("impossible");
else printf("%d\n", (LL)b / d * x % m);
}
return 0;
}