1 条题解
-
0
题意分析
本题要求求解二元一次方程组的解,具体需要处理以下情况:
- 输入包含多组测试用例,每组包含两个方程
- 方程形式为形如
2x + 3y = x
或5 = x + y + 3
的字符串 - 输出要求:
- 若有唯一解,以最简分数形式输出x和y
- 若无唯一解(无穷多解或矛盾),输出"don't know"
- 每组输出间用空行分隔
解题思路
-
问题建模:
- 将每个方程转化为标准形式:
ax + by = c
- 方程组可表示为: [ \begin{cases} a_1x + b_1y = c_1 \ a_2x + b_2y = c_2 \end{cases} ]
- 将每个方程转化为标准形式:
-
解的判定:
- 计算行列式 ( \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} )(无穷多解)
- 否则为矛盾方程(无解)
-
实现关键点:
- 方程字符串解析:提取系数和常数项
- 分数运算:避免浮点数精度问题,使用分数类
- 边界处理:处理系数为0、负号等特殊情况
实现步骤
1. 数据结构设计
- 分数类(Fraction):
- 存储分子(num)和分母(den)
- 实现归一化(normalize)方法,确保分母为正且分数最简
- 重载比较运算符,便于解的判定
2. 方程解析流程
- 分割方程字符串:按空格分割为标记(token)
- 符号处理:跟踪当前项的符号(+/-)
- 项类型判断:
- 变量项(x/y):提取系数
- 常数项:直接提取数值
- 方程转换:将方程转换为
ax + by = c
形式
3. 方程组求解算法
- 标准形式提取:从两个方程中提取 (a_1, b_1, c_1, a_2, b_2, c_2)
- 行列式计算:(\Delta = a_1b_2 - a_2b_1)
- 解的分类处理:
- 唯一解: [ 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
- 上传者