2024.10.4 P1022 题解

· · 题解

模拟题,考验细心程度。捋清楚思路即可

由题意,本题实际上就是求解一个一元一次方程,而且运算符号只含有加减法,因此难度大大降低,无需考虑优先级。换言之,只需求出一次项系数 y 和常数之和 x 即可求出 ans= \frac{x}{y}

具体思路

  1. 分别枚举字符串左部分,如果找到字母,则向前枚举元素,当元素不是数字时停止枚举,期间将各个数字拼接形成一个整数;右部分同理。

  2. 为了防止重复计算,要将枚举过的元素因删除(令 a_i=' ')

    void todel(int st, int x){
    for (int i = st; i > st-x; i--){
        a[i] = ' ';
    }
    }
  3. 令两部分的和为 sum1sum2,根据等式的性质, 显然sum2 应移项至左半部分,即 y=sum1-sum2

// 处理未知项系数 
    int sum1 = 0, sum2 =0; 
    for (int i = 0; i < a.size();i++){
        if (a[i] == '='){
            nx = i;
            break;
        }
        if (a[i] >= 'a' && a[i] <='z'){
            sum1 += fdsum(i);
            int t = fdlen(i);
            todel(i, t);
        }
    }
    int j = 0;
    if (nx != -1){
        for (int i = nx; i <a.size(); i++){
            if (a[i] == '-' && (a[i+1] >= 'a' && a[i+1] <= 'z')) a[i] = '+';
            else if (a[i] == '+' && (a[i+1] >= 'a' && a[i+1] <= 'z')) a[i] = '-';
            if (a[i] >= 'a' && a[i] <='z'){
                sum2 += fdsum(i);
                int t = fdlen(i);
                todel(i, t);
            }
        }
    }
    y = sum1-sum2;
// 求常数系数和 
int fdsum2(int x){
    if(x==0) return a[0] - '0';
    if (x==1) {
        if (a[0] == '-') return (a[1]-'0') - 2*(a[1]-'0');  
    }
    int res = 0,tmp = 0,cnt = 1;
    for (int i = x; i >= 0; i--){       
        if (a[i] >= '0' && a[i] <= '9') tmp += cnt * (a[i] - '0'),cnt *= 10;
        else{
            if (a[i] == '-'){
                if (tmp != 0) tmp -= 2*tmp;
                else return 0;
            }
            else{
                if (tmp == 0) return res;       
            }
        }
    }
    res += tmp;
    return res;
}

(2)枚举左半部分常数元素时应确保以常数的最后一位数字开始向左枚举。即:对于…+36=……,应从6开始向左枚举而不是从3开始向左枚举。为了处理这个问题,可以多加一个特判:

if (a[i] >= '0' && a[i] <= '9' && (a[i+1] < '0' || a[i+1] > '9'))
  1. 同求一次项系数思路,令左半部分之和为 sum3右半部分为 sum4 根据等式的性质, 显然sum3 应移项至右半部分,即 x=sum4-sum3
    //处理常数项:将等号两边常数求和,用右边的减左边的
    int sum3 = 0, sum4 = 0; // the sum of leftSide & RightSide
    // leftSide
    for (int i = 0; i < nx; i++){
        if (a[i] >= '0' && a[i] <= '9' && (a[i+1] < '0' || a[i+1] > '9')){
            sum3 += fdsum2(i);
            int t = fdlen(i);
            todel(i,t);
        }
    } 
    // rightSide
    for (int i = a.size() - 1; i >= nx+1; i--){
        if (a[i] >= '0' && a[i] <= '9'){
            sum4 += fdsum2(i);
            int t = fdlen(i);
            todel(i,t);
        }
    } 
    x = sum4-sum3;
ans = (y == 0) ? 0 : (double)x / (double)y;
printf("%c=%.3lf\n", ch,ans);