复赛三:一元二次方程(uqe)

洛谷:P9750
OJ:P4980

代码分析:

  1. 最大公因数计算:函数 gcd() 用于计算两个数的最大公因数,并将结果输出成最简分数的形式。它主要用于输出解的有理数部分。
  2. 判定平方数与平方因子:函数 gcd2() 用于判断一个数是否为平方数;gcd1() 则用于判断该数是否含有平方因子。这两个函数帮助处理当解含有无理数的情况。
  3. 方程解的判定:根据 Δ 的值(判别式),分别处理无实数解、相等实数解和不同实数解的情况。如果 Δ<0 则无解;若 Δ=0,计算单一解;若 Δ>0,进一步计算有理数或无理数解。

代码逻辑:

  • 先输入方程系数 a, b, c,并将方程标准化(系数变为正)。
  • 计算判别式 Δ。
  • 根据 Δ 的不同情况,输出实数解或者无解,具体输出按最简分数或者包含平方根的形式。

代码实现:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;

// 计算两个数 d 和 e 的最大公因数,并将其化简成最简形式
void gcd(int d, int e) {
    int f, i = 2;
    f = min(abs(d), e);  // 获取 d 和 e 中的较小值
    while (i <= f) {
        if (d % i == 0 && e % i == 0) {
            d = d / i;   // 化简分子
            e = e / i;   // 化简分母
        } else {
            i++;
        }
    }
    // 输出化简后的结果
    if (e == 1) {
        cout << d;  // 如果分母为 1,输出整数
    } else {
        cout << d << '/' << e;  // 否则输出分数
    }
}

// 判断 d 是否可以被某个平方数整除,即判断是否存在 n > 1 使 d % (n^2) == 0
bool gcd1(int d) {
    int n = 0;
    for (int i = 2; i * i < d; i++) {
        if ((d % (i * i)) == 0) n = i;
    }
    return n != 0;  // 如果存在这样的数,则返回 true
}

// 判断 d 是否为某个整数的平方
bool gcd2(int d) {
    for (int i = 1; i < d; i++) {
        if (d == i * i) return true;
    }
    return false;
}

int main() {
    int n, m;  // n 表示方程数量,m 表示系数绝对值的上限
    int f, g, h;
    cin >> n >> m;  // 输入方程数量和系数上限
    vector<int> a(n + 1, 0);
    vector<int> b(n + 1, 0);
    vector<int> c(n + 1, 0);

    // 输入每个方程的系数 a, b, c,并将系数转化为非负处理
    for (int i = 1; i <= n; i++) {
        cin >> f >> g >> h;
        if (f > 0) {
            a[i] = f;
            b[i] = g;
            c[i] = h;
        } else {
            a[i] = -f;
            b[i] = -g;
            c[i] = -h;
        }
    }

    int delt;  // 定义 delta 变量用于判断解的情况
    for (int i = 1; i <= n; i++) {
        delt = b[i] * b[i] - 4 * a[i] * c[i];  // 计算 discriminant Δ = b^2 - 4ac
        // 如果 Δ == 0 且 b == 0,表示方程的解是 0
        if (delt == 0 && b[i] == 0) {
            cout << 0 << '\n';
            continue;
        }

        // 如果 Δ < 0,无实数解
        if (delt < 0) cout << "NO";
        // 如果 Δ == 0,且有实数解
        if (delt == 0) {
            if (b[i] == 0) cout << 0;  // 特殊情况,直接输出 0
            else gcd(-b[i], 2 * a[i]);  // 否则,输出化简后的解
        }

        // 如果 Δ == 1,则解为有理数,按分数形式输出
        if (delt == 1) {
            if ((-b[i] + 1) == 0) cout << 0;
            else gcd(-b[i] + 1, 2 * a[i]);
        }

        // 如果 Δ > 0 且不等于 1
        if (delt > 0 && delt != 1) {
            // 如果 Δ 不是平方数,先输出有理部分再输出无理数部分
            if ((b[i] != 0) && (!gcd2(delt))) {
                gcd(-b[i], 2 * a[i]);
                cout << '+';
            }

            // 如果 Δ 是平方数,直接输出解
            if (gcd2(delt)) {
                if ((-b[i] + sqrt(delt)) == 0) cout << 0;
                else gcd(-b[i] + sqrt(delt), 2 * a[i]);
            }
            // 处理 Δ 为非平方数的情况
            else if (gcd1(delt)) {
                int n = 0;
                for (int i = 2; i * i < delt; i++) {
                    if (delt % (i * i) == 0) n = i;
                }

                int m = n;
                int e = 2 * a[i];
                int f = min(m, e);
                int i = 2;
                // 对 sqrt 部分进行化简
                while (i <= f) {
                    if (m % i == 0 && e % i == 0) {
                        m = m / i;
                        e = e / i;
                    } else {
                        i++;
                    }
                }
                // 输出化简后的无理数部分
                if (e == 1) {
                    if (m != 1) cout << m << '*' << "sqrt(" << delt / (n * n) << ")";
                    else cout << "sqrt(" << delt / (n * n) << ")";
                } else {
                    if (m != 1) cout << m << '*' << "sqrt(" << delt / (n * n) << ")/" << e;
                    else cout << "sqrt(" << delt / (n * n) << ")/" << e;
                }
            }
            // 处理无理数部分
            else {
                cout << "sqrt(" << (b[i] * b[i] - 4 * a[i] * c[i]) << ")/" << 2 * a[i];
            }
        }
        cout << '\n';
    }
}
Scroll to Top