[NOIP2000 普及组] 计算器的改良

发布时间 2023-08-13 09:34:16作者: sleepwind

题目描述

输入一个一元一次方程,求它的解(精确到小数点后三位)。

方程中,只包含整数、小写字母及 \(\texttt{+}\)\(\texttt{-}\)\(\texttt{=}\) 这三个数学符号(当然,符号“\(\texttt{-}\)”既可作减号,也可作负号)。

方程中并没有括号,也没有除号,方程中的字母表示未知数。

键入的一元一次方程均为合法的,且有唯一实数解。

分析

回顾一下解一元一次方程的过程,可以发现,所有步骤都是为了将未知数放在等号一边(左边),常量放在等号另一边(右边),然后将系数化为一。
因此,可以分析读入的方程,将数字加在一起,未知数的系数加在一起,最后计算。
注意处理好未知数系数为一的情况。

代码

#include <iostream>
#include <string>

using namespace std;

string t;
int l, r, x/*未知数系数和*/, n/*常量和*/, mid;
int main() {
    cin >> t;
    x = 0;
    while (t[mid] != '=') mid++; //找到等号
    for (int i = 0; i < t.length(); i++)//寻找未知数并输出
        if (t[i] >= 'a' && t[i] <= 'z') {
            cout << t[i] << '=';
            break;
        }

    //处理未知数系数为一的情况
    if (t[0]>='a'&&t[0]<='z') {
        t[0]=0;
        x++;
    }
    if (t[mid+1]>='a'&&t[mid+1]<='z') {
        t[mid+1]=0;
        x++;
    }

    for (int i=0; i < mid; i++) {
        if (t[i] >= '0' && t[i] <= '9') {
            l = r = i;
            while (t[r+1] >= '0' && t[r+1] <= '9') r++;
            if (r < t.length())
                if (t[r+1] >= 'a' && t[r-1] <= 'z') {
                    if (l == 0) {
                        x += atoi(t.substr(l, r-l+1).c_str());
                        for (int k = l; k <= r; k++) t[k] = 0;
                    }
                    else {
                        if (t[l-1] == '-')
                            x -= atoi(t.substr(l, r - l + 1).c_str());
                        else
                            x += atoi(t.substr(l, r - l + 1).c_str());
                        for (int k=l-1; k <= r; k++) t[k] = 0;
                    }
                    continue;
                }
            if (l == 0) {
                n -= atoi(t.substr(l, r-l+1).c_str());
                for (int k = l; k <= r; k++) t[k] = 0;
            }
            else {
                if (t[l-1] == '-')
                    n += atoi(t.substr(l, r - l + 1).c_str());
                else
                    n -= atoi(t.substr(l, r - l + 1).c_str());
                for (int k=l-1; k <= r; k++) t[k] = 0;
            }
        }
    }

    //注意等号左右未知数系数与常量的加减情况是相反的
    for (int i=mid+1; i < t.length(); i++) {
        if (t[i] >= '0' && t[i] <= '9') {
            l = r = i;
            while (t[r+1] >= '0' && t[r+1] <= '9') r++;
            if (r < t.length())
                if (t[r+1] >= 'a' && t[r-1] <= 'z') {
                    if (l == 0) {
                        x -= atoi(t.substr(l, r - l + 1).c_str());
                        for (int k = l; k <= r; k++) t[k] = 0;
                    }
                    else {
                        if (t[l-1] == '-')
                            x += atoi(t.substr(l, r - l + 1).c_str());
                        else
                            x -= atoi(t.substr(l, r - l + 1).c_str());
                        for (int k = l - 1; k <= r; k++) t[k] = 0;
                    }
                    continue;
                }
            if (t[l-1] == '-')
                n -= atoi(t.substr(l, r - l + 1).c_str());
            else
                n += atoi(t.substr(l, r - l + 1).c_str());
            for (int k = l - 1; k <= r; k++) t[k] = 0;
        }
    }
    printf("%.3lf", double(n) / x);
    return 0;
}