给定 n 组数据 ai,bi,mi,对于每组数求出一个 xi,使其满足 ai × xi ≡ bi (mod mi),如果无解则输出 impossible。
输入格式
第一行包含整数 n。
接下来 n 行,每行包含一组数据 ai,bi,mi。
输出格式
输出共 n 行,每组数据输出一个整数表示一个满足条件的 xi,如果无解则输出 impossible。
每组数据结果占一行,结果可能不唯一,输出任意一个满足条件的结果均可。
输出答案必须在 int 范围之内。
数据范围
1≤n≤10^5,
1≤ai,bi,mi≤2×10^9
输入样例:
2
2 3 6
4 3 5
输出样例:
impossible
-3
推理:
因为 a ∗ x ≡ b(mod m) 等价于 a ∗ x − b 是 m 的倍数,因此线性同余方程等价为 a ∗ x + m ∗ y = b
设 d = gcd(a,m),
根据 裴蜀定理,上述等式有解当且仅当 b 是 d 的倍数(即 d | b 或 b % d == 0,当 b 不是 d 的倍数直接说明无解)
因此先用扩展欧几里得算法求出一组整数 x’、y’(实际在本题中我们仅需要 x’), 先使得 a ∗ x’ + m ∗ y’ = d。
之后 x = x’ ∗ b / d % m 即是所求。(在 x’ 基础上扩大 b / d 倍,注意要 mod m,由于 b 始终是 >= d 的,不存在精度缺失,此处无需改写为 * d^(-1) mod m)
当然题目要求解出这个线性同余方程组,我们只需求出 x 即可。
数据范围是1e5,建议用scanf读入,还有,注意用long long
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,a,b,m;
int x,y;
void exgcd(int a, int m, int &d, int &x, int &y)
{
if(!m)
{
d = a, x = 1,y = 0;
return ;
}
exgcd(m,a%m,d,y,x), y-=a/m*x;
}
signed main()
{
scanf("%lld",&n);
while(n--)
{
scanf("%lld%lld%lld",&a,&b,&m);
int d;//a和m的最大公约数
exgcd(a,m,d,x,y);
if(b%d) printf("impossible\n");//当 b 不是 d 的倍数直接说明无解
else
{
printf("%lld\n",x*(b/d)%m);
}
}
return 0;
}