66.Acwing基础课第877题-简单-扩展欧几里得算法

66.Acwing基础课第877题-简单-扩展欧几里得算法

题目描述

\(给定 n 对正整数 a_i,b_i,对于每对数,求出一组 x_i,y_i,使其满足 a_i×x_i+b_i×y_i=gcd(a_i,b_i)\)

输入格式

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

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

输出格式

\(输出共 n 行,对于每组 a_i,b_i,求出一组满足条件的 x_i,y_i,每组结果占一行\)

\(本题答案不唯一,输出任意满足条件的 x_i,y_i 均可\)

数据范围

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

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

输入样例:

2
4 6
8 18

输出样例:

-1 1
-2 1

代码:

// 包含输入输出流头文件(cin/cout依赖,本代码用C风格IO,保留作为通用模板)
#include <iostream>
#include <algorithm>

using namespace std;

// 扩展欧几里得算法核心函数
// 功能:求解 ax + by = gcd(a, b) 的一组整数解 (x, y),并返回gcd(a, b)
// 参数说明:
//   a, b:方程的系数
//   x, y:引用传递,用于存储求得的一组解
// 返回值:d = gcd(a, b)(a和b的最大公约数)
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);
    
    // 回溯推导解:从递归边界反向计算当前层的x,y
    // 推导依据:
    // 假设递归得到 b*x' + (a%b)*y' = d
    // 而 a%b = a - (a/b)*b(a/b是整数除法)
    // 代入得:b*x' + (a - (a/b)*b)*y' = d → a*y' + b*(x' - (a/b)*y') = d
    // 对比 ax + by = d,可得:x = y', y = x' - (a/b)*y'
    // 由于递归时已经交换了x和y(当前x是原来的y',当前y是原来的x')
    // 因此简化为:y -= a/b * x
    y -= a / b * x;
    
    return d; // 返回最大公约数
}

int main()
{
    int n; // n:测试用例的组数
    // C风格输入:比cin更快,适合竞赛大数据量场景
    scanf("%d", &n);
    
    // 循环处理n组测试用例
    while (n -- )
    {
        int a, b; // a, b:需要求解 ax + by = gcd(a,b) 的系数
        scanf("%d%d", &a, &b);
        
        int x, y; // 存储方程的一组解
        exgcd(a, b, x, y); // 调用扩展欧几里得算法求解
        
        // 输出求得的一组特解x和y
        printf("%d %d\n", x, y);
    }

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