1 条题解

  • 0

    题意分析

    本题要求求解二元一次方程组的解,具体需要处理以下情况:

    1. 输入包含多组测试用例,每组包含两个方程
    2. 方程形式为形如 2x + 3y = x5 = x + y + 3 的字符串
    3. 输出要求:
      • 若有唯一解,以最简分数形式输出x和y
      • 若无唯一解(无穷多解或矛盾),输出"don't know"
      • 每组输出间用空行分隔

    解题思路

    1. 问题建模

      • 将每个方程转化为标准形式:ax + by = c
      • 方程组可表示为: [ \begin{cases} a_1x + b_1y = c_1 \ a_2x + b_2y = c_2 \end{cases} ]
    2. 解的判定

      • 计算行列式 ( \Delta = a_1b_2 - a_2b_1 )
      • 若 ( \Delta \neq 0 ):有唯一解,利用克莱姆法则求解
      • 若 ( \Delta = 0 ):
        • 检查是否 ( \frac{a_1}{a_2} = \frac{b_1}{b_2} = \frac{c_1}{c_2} )(无穷多解)
        • 否则为矛盾方程(无解)
    3. 实现关键点

      • 方程字符串解析:提取系数和常数项
      • 分数运算:避免浮点数精度问题,使用分数类
      • 边界处理:处理系数为0、负号等特殊情况

    实现步骤

    1. 数据结构设计

    • 分数类(Fraction)
      • 存储分子(num)和分母(den)
      • 实现归一化(normalize)方法,确保分母为正且分数最简
      • 重载比较运算符,便于解的判定

    2. 方程解析流程

    1. 分割方程字符串:按空格分割为标记(token)
    2. 符号处理:跟踪当前项的符号(+/-)
    3. 项类型判断
      • 变量项(x/y):提取系数
      • 常数项:直接提取数值
    4. 方程转换:将方程转换为 ax + by = c 形式

    3. 方程组求解算法

    1. 标准形式提取:从两个方程中提取 (a_1, b_1, c_1, a_2, b_2, c_2)
    2. 行列式计算:(\Delta = a_1b_2 - a_2b_1)
    3. 解的分类处理
      • 唯一解: [ x = \frac{b_2c_1 - b_1c_2}{\Delta}, \quad y = \frac{a_1c_2 - a_2c_1}{\Delta} ]
      • 无穷多解:所有比例相等((\frac{a_1}{a_2} = \frac{b_1}{b_2} = \frac{c_1}{c_2}))
      • 无解:比例不全相等(矛盾方程)

    4. 输出格式化

    • 整数形式:分母为1时直接输出分子
    • 分数形式:输出"分子/分母"
    • 特殊情况:输出"don't know"

    代码实现(C++)

    #include <iostream>
    #include <string>
    #include <vector>
    #include <sstream>
    #include <algorithm>
    #include <cstdio>  // 添加了cstdio头文件
    using namespace std;
    
    // 计算最大公约数
    long long gcd(long long a, long long b) {
        return b == 0 ? a : gcd(b, a % b);
    }
    
    // 分数类,用于精确表示有理数
    struct Fraction {
        long long num, den;
        
        Fraction(long long n = 0, long long d = 1) : num(n), den(d) {
            normalize();
        }
        
        void normalize() {
            if (den == 0) {
                num = 0;
                den = 1;
                return;
            }
            
            if (den < 0) {
                num = -num;
                den = -den;
            }
            
            long long g = gcd(abs(num), den);
            if (g != 0) {
                num /= g;
                den /= g;
            }
        }
        
        bool operator==(const Fraction& other) const {
            return num == other.num && den == other.den;
        }
        
        bool operator!=(const Fraction& other) const {
            return !(*this == other);
        }
    };
    
    // 解析方程,提取系数
    pair<pair<Fraction, Fraction>, Fraction> parseEquation(const string& eq) {
        Fraction a(0), b(0), c(0);
        bool isRight = false;
        stringstream ss(eq);
        string token;
        
        // 初始符号为正
        int sign = 1;
        long long coeff = 0;
        bool hasCoeff = false;
        char var = ' ';
        
        while (ss >> token) {
            if (token == "=") {
                isRight = true;
                sign = 1;
                continue;
            }
            
            if (token == "+") {
                sign = 1;
                continue;
            }
            
            if (token == "-") {
                sign = -1;
                continue;
            }
            
            // 解析项
            coeff = 0;
            hasCoeff = false;
            var = ' ';
            
            for (size_t i = 0; i < token.size(); ++i) {
                char c = token[i];
                if (c == 'x' || c == 'y') {
                    var = c;
                    break;
                }
                coeff = coeff * 10 + (c - '0');
                hasCoeff = true;
            }
            
            if (hasCoeff && coeff == 0) {
                // 特殊情况: 单独的负号
                coeff = 1;
                hasCoeff = true;
            }
            
            if (!hasCoeff) {
                coeff = 1;
            }
            
            if (var == ' ') {
                // 常数项
                long long val = sign * coeff;
                if (isRight) val = -val;
                c.num += val;
            } else {
                // 变量项
                long long val = sign * coeff;
                if (isRight) val = -val;
                
                if (var == 'x') {
                    a.num += val;
                } else {
                    b.num += val;
                }
            }
        }
        
        return make_pair(make_pair(a, b), c);
    }
    
    // 求解二元一次方程组
    pair<Fraction, Fraction> solveEquations(
        const pair<pair<Fraction, Fraction>, Fraction>& eq1,
        const pair<pair<Fraction, Fraction>, Fraction>& eq2) {
        
        Fraction a1 = eq1.first.first;
        Fraction b1 = eq1.first.second;
        Fraction c1 = eq1.second;
        
        Fraction a2 = eq2.first.first;
        Fraction b2 = eq2.first.second;
        Fraction c2 = eq2.second;
        
        // 计算行列式
        Fraction det(a1.num * b2.num - a2.num * b1.num, a1.den * b2.den);
        
        if (det.num == 0) {
            // 检查是否矛盾或有无穷多解
            // 转换为标准形式 ax + by = c
            // 检查 a1/a2 == b1/b2 == c1/c2
            
            // 检查是否所有比例都相等
            bool a_ratio_ok = true;
            bool b_ratio_ok = true;
            bool c_ratio_ok = true;
            
            if (a2.num != 0) {
                a_ratio_ok = (a1.num * a2.den == a2.num * a1.den);
            } else {
                a_ratio_ok = (a1.num == 0);
            }
            
            if (b2.num != 0) {
                b_ratio_ok = (b1.num * b2.den == b2.num * b1.den);
            } else {
                b_ratio_ok = (b1.num == 0);
            }
            
            if (c2.num != 0) {
                c_ratio_ok = (c1.num * c2.den == c2.num * c1.den);
            } else {
                c_ratio_ok = (c1.num == 0);
            }
            
            if (a_ratio_ok && b_ratio_ok && c_ratio_ok) {
                // 有无穷多解
                return make_pair(Fraction(0, 0), Fraction(0, 0));
            } else {
                // 矛盾方程
                return make_pair(Fraction(0, 0), Fraction(0, 0));
            }
        } else {
            // 有唯一解
            Fraction x_num(b2.num * c1.num - b1.num * c2.num, b2.den * c1.den);
            Fraction x_den = det;
            Fraction x(x_num.num * x_den.den, x_num.den * x_den.num);
            
            Fraction y_num(a1.num * c2.num - a2.num * c1.num, a1.den * c2.den);
            Fraction y_den = det;
            Fraction y(y_num.num * y_den.den, y_num.den * y_den.num);
            
            return make_pair(x, y);
        }
    }
    
    // 输出分数,处理特殊情况
    string formatFraction(const Fraction& f) {
        if (f.den == 0) {
            return "don't know";
        }
        
        // 检查是否有无穷多解或矛盾
        if (f.num == 0 && f.den == 1) {
            return "don't know";
        }
        
        if (f.den == 1) {
            char buffer[20];
            sprintf(buffer, "%lld", f.num);
            return string(buffer);
        } else {
            char buffer[40];
            sprintf(buffer, "%lld/%lld", f.num, f.den);
            return string(buffer);
        }
    }
    
    int main() {
        int n;
        cin >> n;
        cin.ignore();  // 忽略第一行后的换行符
        
        for (int i = 0; i < n; ++i) {
            // 读取两个方程
            string eq1, eq2;
            getline(cin, eq1);
            getline(cin, eq2);
            
            // 处理空行
            if (i < n - 1) {
                string empty;
                getline(cin, empty);
            }
            
            // 解析方程
            pair<pair<Fraction, Fraction>, Fraction> parsed1 = parseEquation(eq1);
            pair<pair<Fraction, Fraction>, Fraction> parsed2 = parseEquation(eq2);
            
            // 求解
            pair<Fraction, Fraction> solution = solveEquations(parsed1, parsed2);
            
            // 输出结果
            cout << formatFraction(solution.first) << endl;
            cout << formatFraction(solution.second) << endl;
            
            // 空行分隔
            if (i < n - 1) {
                cout << endl;
            }
        }
        
        return 0;
    }
    
    • 1

    信息

    ID
    1348
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    16
    已通过
    1
    上传者