题目地址:
https://www.acwing.com/problem/content/880/
给定
n
n
n组数
a
i
,
b
i
,
m
i
a_i,b_i,m_i
ai,bi,mi,求同余方程
a
i
x
≡
b
i
(
m
o
d
m
i
)
a_ix\equiv b_i(\mod m_i)
aix≡bi(modmi)的解。若无解,则输出impossible
。
输入格式:
第一行包含整数
n
n
n。接下来
n
n
n行,每行包含一组数据
a
i
,
b
i
,
m
i
a_i,b_i,m_i
ai,bi,mi。
输出格式:
输出共
n
n
n行,每组数据输出一个整数表示一个满足条件的
x
i
x_i
xi,如果无解则输出impossible。每组数据结果占一行,结果可能不唯一,输出任意一个满足条件的结果均可。输出答案必须在int范围之内。
数据范围:
1
≤
n
≤
1
0
5
1\le n\le 10^5
1≤n≤105
1
≤
a
i
,
b
i
,
m
i
≤
2
×
1
0
9
1\le a_i,b_i,m_i\le 2\times 10^9
1≤ai,bi,mi≤2×109
其实就是求 a x + m y = b ax+my=b ax+my=b的一组解,这可以用扩展欧几里得算法来求。如果 ( a , m ) ∤ b (a,m)\not |b (a,m)∣b,则无解,否则先求出 a x + m y = ( a , m ) ax+my=(a,m) ax+my=(a,m)的一组解,然后两边乘以 b ( a , m ) \frac{b}{(a,m)} (a,m)b即可。代码如下:
#include <iostream>
using namespace std;
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;
cin >> 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 == 0) printf("%d\n", (long) x * (b / d) % m);
else puts("impossible");
}
}
每次询问时空复杂度 O ( log min { a , m } ) O(\log \min\{a,m\}) O(logmin{a,m})。