67.Acwing基础课第878题-简单-线性同余方程

67.Acwing基础课第878题-简单-线性同余方程

题目描述

\(给定 n 组数据 a_i,b_i,m_i,对于每组数求出一个 x_i,使其满足 a_i×x_i≡b_i(mod\ m_i),如果无解则输出 impossible\)

输入格式

\(第一行包含整数 n\)

\(接下来 n 行,每行包含三个整数 a_i,p_i,m_i\)

输出格式

输出共 n 行,每组数据输出一个整数表示一个满足条件的 \(x_i\),如果无解则输出 impossible

每组数据结果占一行,结果可能不唯一,输出任意一个满足条件的结果均可。

输出答案必须在 int 范围之内。

数据范围

\(1≤n≤10^5\),

\(1≤a_i,b_i,m_i≤2×10^9\)

输入样例:

2
2 3 6
4 3 5

输出样例:

impossible
-3

代码:

// 包含输入输出流头文件(cin/cout依赖,本代码用C风格IO,更适合竞赛大数据量)
#include <iostream>
#include <algorithm>

using namespace std;

// 定义长整型别名:防止乘法/取模过程中溢出int范围
typedef long long LL;

// 扩展欧几里得算法核心函数
// 功能:求解 ax + my = gcd(a, m) 的一组整数解 (x, y),并返回gcd(a, m)
// 参数说明:
//   a, m:方程的系数(对应线性同余方程的 a 和模数 m)
//   x, y:引用传递,存储求得的一组解
// 返回值:d = gcd(a, m)(a和m的最大公约数)
int exgcd(int a, int b, int &x, int &y)
{
    // 递归边界:当b=0时,方程变为 a*1 + 0*0 = a,即gcd(a,0)=a
    if (!b)
    {
        x = 1, y = 0; // 此时特解为x=1,y=0
        return a;     // 返回最大公约数a
    }
    // 递归调用:欧几里得算法核心(gcd(a,b)=gcd(b,a%b))
    // 注意:递归时交换x和y的位置,简化后续解的推导
    int d = exgcd(b, a % b, y, x);
    
    // 回溯推导当前层的解:
    // 推导依据:b*x' + (a%b)*y' = d → 整理得 a*y' + b*(x' - (a/b)*y') = d
    // 因递归交换了x/y,当前x=y',y=x',故简化为 y -= a/b * x
    y -= a / b * x;
    
    return d; // 返回a和b的最大公约数
}

int main()
{
    int n; // n:测试用例的组数
    // C风格输入:比cin更快,适合竞赛场景
    scanf("%d", &n);
    
    // 循环处理n组测试用例(每组求解线性同余方程 a*x ≡ b (mod m))
    while (n -- )
    {
        int a, b, m; 
        // a:线性同余方程的系数;b:余数;m:模数
        // 目标:求解 a*x ≡ b (mod m) 的一个整数解x
        scanf("%d%d%d", &a, &b, &m);

        int x, y; // 存储扩展欧几里得算法的解
        // 调用exgcd求解 a*x + m*y = gcd(a, m)
        int d = exgcd(a, m, x, y);
        
        // 线性同余方程有解的充要条件:gcd(a,m) 能整除 b(即 b % d == 0)
        if (b % d) 
            puts("impossible"); // 无解,输出impossible
        else 
        {
            // 有解时,先求原方程 a*x = b 的一个特解,再调整为模m的解:
            // 1. 扩展欧几里得求得的x是 a*x + m*y = d 的解 → 两边乘 b/d 得 a*(x*b/d) + m*(y*b/d) = b
            // 2. 因此 x0 = x * (b/d) 是 a*x ≡ b (mod m) 的一个特解
            // 3. 对m取模,保证解在合理范围内;(LL)强制转换防止溢出
            printf("%d\n", (LL)b / d * x % m);
        }
    }

    return 0; // 程序正常结束
}
posted @ 2026-04-09 16:46  CodeMagicianT  阅读(9)  评论(0)    收藏  举报