当前位置:首页 > 洛谷 > 洛谷P2833题解:扩展欧几里得算法求解线性方程整数解(详细步骤+代码实现)

洛谷P2833题解:扩展欧几里得算法求解线性方程整数解(详细步骤+代码实现)

5个月前 (07-25)

洛谷P2833题解:扩展欧几里得算法求解线性方程整数解(详细步骤+代码实现) 洛谷题解 欧几里得算法 线性方程 C++ 第1张

一、题目解读

洛谷P2833题目要求求解线性方程 ax + by = c 在给定矩形区域 (x1, x2) × (y1, y2) 内的整数解数量。需处理系数 a, b 为0的特殊情况,并结合约束条件计算可行解的个数。问题核心在于将数学理论转化为编程实现,考验对扩展欧几里得算法的掌握。

二、解题思路

1. 核心算法:利用扩展欧几里得算法(EGCD)求解线性方程的通解形式,通过系数 a, b 的最大公约数 d 判断是否有解。

2. 边界处理:针对 a=0 或 b=0 的退化情况,分别计算单一变量的解范围。

3. 通解推导:通过特解 (x0, y0) 和系数关系,推导出通解 x = x0 + b*t, y = y0 - a*t,结合区间约束计算整数 t 的合法范围。

4. 优化细节:使用 ceil/floor 函数精确计算边界,避免浮点数误差。

三、解题步骤

1. 调用EGCD函数:定义 extended_gcd 递归计算 a, b 的GCD及系数 x, y,作为后续求解的基础。

2. 处理全0系数:若 a=b=0,方程恒成立时直接计算矩形区域面积;否则判断 c=0 是否成立。

3. 单系数0处理:当 a=0 或 b=0 时,将方程转化为单一变量求解,结合区间判断解的存在性。

4. 计算特解与调整:通过EGCD结果得到特解 (x0, y0),根据系数符号调整方向。

5. 推导通解范围:利用通解公式计算 t 的上下界 t_low, t_high,确保解在矩形区域内。

6. 返回解数量:若 t 区间合法,计算区间长度并输出。

四、代码与注释

#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;

// 扩展欧几里得算法,求解 ax + by = gcd(a, b) 的系数
long long extended_gcd(long long a, long long b, long long &x, long long &y) {
    if (b == 0) {  // 递归终止条件
        x = 1;
        y = 0;
        return a;  // GCD(a, 0) = a
    }
    long long d = extended_gcd(b, a % b, y, x);  // 递归调用
    y -= a / b * x;  // 系数回推公式
    return d;
}

// 计算线性方程在矩形区域内的整数解数量
long long count_solutions(long long a, long long b, long long c,
                         long long x1, long long x2,
                         long long y1, long long y2) {
    // 处理全0系数(方程恒成立或矛盾)
    if (a == 0 && b == 0) {
        return c == 0? (x2 - x1 + 1) * (y2 - y1 + 1) : 0;
    }
    
    // a=0 时方程变为 by = c
    if (a == 0) {
        if (b == 0) return 0;  // 矛盾情况
        if (c % b!= 0) return 0;  // 无解
        long long y = -c / b;  // 特解
        return (y >= y1 && y <= y2)? (x2 - x1 + 1) : 0;  // 计算x区间长度
    }
    
    // b=0 时同理
    if (b == 0) {
        if (a == 0) return 0;  // 矛盾
        if (c % a!= 0) return 0;
        long long x = -c / a;
        return (x >= x1 && x <= x2)? (y2 - y1 + 1) : 0;
    }

    // 计算GCD并判断是否有解
    long long x0, y0;
    long long d = extended_gcd(abs(a), abs(b), x0, y0);  // 确保a, b非负
    if (c % d!= 0) return 0;  // 无解条件

    // 调整特解符号(根据a, b实际符号)
    x0 *= (a < 0)? -1 : 1;
    y0 *= (b < 0)? -1 : 1;
    x0 *= -c / d;  // 计算特解 (x0, y0)
    y0 *= -c / d;
    a /= d;  // 归一化系数
    b /= d;
    
    // 通解公式 x = x0 + b*t, y = y0 - a*t
    long long t_low = max(ceil((x1 - x0) * 1.0 / b), ceil((y0 - y2) * 1.0 / a));  // t的下界
    long long t_high = min(floor((x2 - x0) * 1.0 / b), floor((y0 - y1) * 1.0 / a));  // t的上界
    return (t_high >= t_low)? (t_high - t_low + 1) : 0;  // 计算合法t的数量
}

int main() {
    ios::sync_with_stdio(false);  // 关闭同步加速输入
    cin.tie(0);
    long long a, b, c, x1, x2, y1, y2;
    cin >> a >> b >> c >> x1 >> x2 >> y1 >> y2;  // 输入参数
    cout << count_solutions(a, b, c, x1, x2, y1, y2) << endl;  // 输出解数量
    return 0;
}

五、总结

本文通过洛谷P2833题的代码实例,展示了扩展欧几里得算法在求解线性方程整数解问题中的完整流程。关键在于理解通解公式与区间约束的结合,以及针对系数特殊情况的分类讨论。代码中的边界处理和符号调整是避免错误的核心细节,建议读者在实际应用中结合数学推导验证算法的正确性。掌握此类算法不仅能提升竞赛解题能力,也为解决实际问题提供数学工具。


原创内容 转载请注明出处

分享给朋友:

相关文章

力扣144:递归之美 轻松掌握二叉树前序遍历

力扣144:递归之美 轻松掌握二叉树前序遍历

题目解读二叉树的前序遍历是一种基础但重要的树遍历方式,其遍历顺序为:先访问根节点,然后递归地前序遍历左子树,最后递归地前序遍历右子树。给定一个二叉树的根节点,我们需要按照这个顺序访问所有节点,并将它们...

【动态规划入门】力扣509题:斐波那契数列的经典解法与优化思路

【动态规划入门】力扣509题:斐波那契数列的经典解法与优化思路

题目解读‌斐波那契数列是一个经典的数学问题,在计算机科学中常被用作算法教学的入门案例。这个神奇的数列从0和1开始,后续每个数字都是前两个数字之和。题目要求我们计算第n个斐波那契数,看似简单的问题背后却...

洛谷1220题解:动态规划与区间DP优化解法(附代码注释)

洛谷1220题解:动态规划与区间DP优化解法(附代码注释)

一、题目解读洛谷1220题要求计算在n个位置放置灯的情况下,通过关闭连续区间灯并移动至区间端点,使得总耗电量最小。需考虑灯的功率与位置差异,设计高效的算法求解最优策略。二、解题思路1. 动态规划 +...

牛客NC67题解:汉诺塔递归算法与解题步骤

牛客NC67题解:汉诺塔递归算法与解题步骤

一、题目解读牛客NC67题要求解决汉诺塔问题,这是一个经典的递归算法题目。题目给定整数n,代表汉诺塔中的盘子数量,需要输出将n个盘子从起始柱移动到目标柱的所有步骤。汉诺塔问题规则为:每次只能移动一个盘...

洛谷1656题解:基于Tarjan算法求解割边问题(附代码与详细步骤)

洛谷1656题解:基于Tarjan算法求解割边问题(附代码与详细步骤)

一、题目解读洛谷1656题要求在无向图中找出所有割边(即删除后导致图不连通的边)。题目核心在于判断图的连通性,并识别哪些边是“桥”。需理解图论中的连通分量概念,以及如何通过算法高效定位割边。二、解题思...

洛谷P2190题解:铁路售票系统车厢计算(差分数组+前缀和优化)

洛谷P2190题解:铁路售票系统车厢计算(差分数组+前缀和优化)

一、题目解读洛谷P2190题要求解决铁路售票系统中的车厢数量计算问题。题目给定n个车站和m条订票申请,每条申请包含区间[x,y)及乘客数z。需要计算在不超载的情况下(每节车厢最多36人),满足所有乘客...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。