首页 > 其他分享 >《【NOIP2000 基础】计算器的改良》 不全对题解

《【NOIP2000 基础】计算器的改良》 不全对题解

时间:2024-11-11 21:47:27浏览次数:3  
标签:NOIP2000 ++ double equation 计算器 pos 题解 rhsConst size

温馨提示,本题难度略大,本人写不出来正确代码,文章代码并不对,只是提供一些思路,希望大家能谅解!

目录

题目描述

输入描述

输出描述

解析

完整代码


描述

NCL是一家专门从事计算器改良与升级的实验室,最近该实验室收到了某公司所委托的一个任务:需要在该公司某型号的计算器上加上解一元一次方程的功能。实验室将这个任务交给了一个刚进入的新手ZL先生。为了很好的完成这个任务,ZL先生首先研究了一些一元一次方程的实例:

4+3x=8
6a-5+1=2-2a
-5+12y=0

编写程序,解输入的一元一次方程, 将解方程的结果(精确至小数点后三位)输出至屏幕。
你可假设对键入的方程的正确性的判断是由另一个程序员在做,或者说可认为键入的一元一次方程均为合法的,且有唯一实数解。
ZL先生被主管告之,在计算器上键入的一个一元一次方程中,只包含整数、小写字母及+、-、=这三个数学符号(当然,符号“─”既可作减号,也可作负号)。方程中并没有括号,也没有除号,方程中的字母表示未知数。

输入描述

一个一元一次方程。

输出描述

解方程的结果(精确至小数点后三位)。

用例输入 1 

6a-5+1=2-2a

用例输出 1 

a=0.750

提示

方程在计算过程中,不会出现超过int范围的整数
【来源】noip2000普及组复赛第1题

来源

noip复赛 字符

 

兄弟们啊,不是你们c++学不会,而是个别老师他教不对啊。

来,就这题你看着懵不懵,懵不懵!

看看老高平时是怎么教我的:

为了完成这个任务,我们需要解析一元一次方程,并求解未知数。以下是解决这个问题的步骤:

  1. 解析方程‌:将输入的字符串方程解析为左右两部分,并提取未知数和常数项。
  2. 整理方程‌:将方程整理为标准形式 ax+b=0。
  3. 求解未知数‌:根据整理后的方程求解未知数,并输出精确到小数点后三位的结果。

我们可以使用简单的字符串处理来实现这个目标。下面是一个可能的C++实现:

 

#include <iostream>
#include <string>
#include <sstream>
#include <cctype>
#include <iomanip>

using namespace std;

// 辅助函数:判断字符是否为运算符
bool isOperator(char c) {
    return c == '+' || c == '-';
}

// 辅助函数:判断字符是否为数字
bool isDigit(char c) {
    return isdigit(c);
}

// 辅助函数:从字符串中提取整数
int extractInt(const string& str, size_t& pos) {
    int num = 0;
    bool negative = false;
    
    // 检查负号
    if (str[pos] == '-') {
        negative = true;
        ++pos;
    }
    
    // 提取数字
    while (pos < str.size() && isDigit(str[pos])) {
        num = num * 10 + (str[pos] - '0');
        ++pos;
    }
    
    return negative ? -num : num;
}

// 辅助函数:提取方程的系数和常数项
void parseEquation(const string& equation, char& variable, double& lhsCoeff, double& lhsConst, double& rhsCoeff, double& rhsConst) {
    size_t pos = 0;
    bool lhs = true;  // 标志当前是在等式的左边还是右边
    
    while (pos < equation.size() && equation[pos] != '=') {
        if (isalpha(equation[pos])) {
            variable = equation[pos];
            // 紧接着的字符应该是运算符或者数字,否则格式不正确(假设输入总是合法的)
            if (pos + 1 < equation.size() && (isDigit(equation[pos + 1]) || isOperator(equation[pos + 1]))) {
                // 如果有运算符,说明有系数,否则系数为1
                if (isOperator(equation[pos + 1]) || pos + 1 == equation.size()) {
                    if (lhs) lhsCoeff = 1;  // 左边系数默认为1
                    else rhsCoeff = 1;      // 右边系数默认为1
                } else {
                    if (lhs) lhsCoeff = extractInt(equation, ++pos);
                    else rhsCoeff = extractInt(equation, ++pos);
                }
            }
        } else if (isDigit(equation[pos]) || isOperator(equation[pos])) {
            // 处理常数项
            int constant = extractInt(equation, pos);
            if (lhs) lhsConst += constant;
            else rhsConst += constant;
        }
        ++pos;
    }
    
    // 转换到等式右边
    if (pos < equation.size() && equation[pos] == '=') {
        lhs = false;
        ++pos;
    }
    
    // 处理等式右边
    while (pos < equation.size()) {
        if (isalpha(equation[pos])) {
            // 右边不应该再出现未知数,假设输入是合法的,所以不需要处理
        } else if (isDigit(equation[pos]) || isOperator(equation[pos])) {
            int constant = extractInt(equation, pos);
            rhsConst += constant;
        }
        ++pos;
    }
}

int main() {
    string equation;
    getline(cin, equation);
    
    char variable;
    double lhsCoeff = 0, lhsConst = 0;
    double rhsCoeff = 0, rhsConst = 0;
    
    parseEquation(equation, variable, lhsCoeff, lhsConst, rhsCoeff, rhsConst);
    
    // ax + b = cx + d  ->  (a-c)x = d-b
    double totalCoeff = lhsCoeff - rhsCoeff;
    double totalConst = rhsConst - lhsConst;
    
    // x = (d-b) / (a-c)
    double solution = totalConst / totalCoeff;
    cout << fixed << setprecision(3) << variable << "=" << solution << endl;
    
    return 0;
}

在这段代码中,isOperator 和 isDigit 是辅助函数,用于判断字符是否为运算符或数字。extractInt 函数用于从字符串中提取整数,考虑到了负号的情况。parseEquation 函数负责解析方程,将方程的系数和常数项提取出来。最后,在 main 函数中,我们读取输入的方程,调用 parseEquation 函数进行解析,然后计算并输出结果。

下面是去掉注释后的代码:

#include <iostream>
#include <string>
#include <sstream>
#include <cctype>
#include <iomanip>

using namespace std;

bool isOperator(char c) {
    return c == '+' || c == '-';
}

bool isDigit(char c) {
    return isdigit(c);
}

int extractInt(const string& str, size_t& pos) {
    int num = 0;
    bool negative = false;
    
    if (str[pos] == '-') {
        negative = true;
        ++pos;
    }
    
    while (pos < str.size() && isDigit(str[pos])) {
        num = num * 10 + (str[pos] - '0');
        ++pos;
    }
    
    return negative ? -num : num;
}

void parseEquation(const string& equation, char& variable, double& lhsCoeff, double& lhsConst, double& rhsCoeff, double& rhsConst) {
    size_t pos = 0;
    bool lhs = true;
    
    while (pos < equation.size() && equation[pos] != '=') {
        if (isalpha(equation[pos])) {
            variable = equation[pos];
            if (pos + 1 < equation.size() && (isDigit(equation[pos + 1]) || isOperator(equation[pos + 1]))) {
                if (isOperator(equation[pos + 1]) || pos + 1 == equation.size()) {
                    if (lhs) lhsCoeff = 1;
                    else rhsCoeff = 1;
                } else {
                    if (lhs) lhsCoeff = extractInt(equation, ++pos);
                    else rhsCoeff = extractInt(equation, ++pos);
                }
            }
        } else if (isDigit(equation[pos]) || isOperator(equation[pos])) {
            int constant = extractInt(equation, pos);
            if (lhs) lhsConst += constant;
            else rhsConst += constant;
        }
        ++pos;
    }
    
    if (pos < equation.size() && equation[pos] == '=') {
        lhs = false;
        ++pos;
    }
    
    while (pos < equation.size()) {
        if (isDigit(equation[pos]) || isOperator(equation[pos])) {
            int constant = extractInt(equation, pos);
            rhsConst += constant;
        }
        ++pos;
    }
}

int main() {
    string equation;
    getline(cin, equation);
    
    char variable;
    double lhsCoeff = 0, lhsConst = 0;
    double rhsCoeff = 0, rhsConst = 0;
    
    parseEquation(equation, variable, lhsCoeff, lhsConst, rhsCoeff, rhsConst);
    
    double totalCoeff = lhsCoeff - rhsCoeff;
    double totalConst = rhsConst - lhsConst;
    
    double solution = totalConst / totalCoeff;
    
    cout << fixed << setprecision(3) << variable << "=" << solution << endl;
    
    return 0;
}

结束了!

对了,忘说了一句话:

要想c++成绩好,就来jiabei小课堂

还有,点我主页,看我简介,别给那三个人点赞就完了

标签:NOIP2000,++,double,equation,计算器,pos,题解,rhsConst,size
From: https://blog.csdn.net/using_namespaces/article/details/143591386

相关文章

  • 洛谷题单103数组题解||by红糖
    P1428小鱼比可爱题目描述人比人,气死人;鱼比鱼,难死鱼。小鱼最近参加了一个“比可爱”比赛,比的是每只鱼的可爱程度。参赛的鱼被从左到右排成一排,头都朝向左边,然后每只鱼会得到一个整数数值,表示这只鱼的可爱程度,很显然整数越大,表示这只鱼越可爱,而且任意两只鱼的可爱程度可能一样......
  • [题解](更新中)Refact.ai Match 1 (Codeforces Round 985)
    A-Set显然答案是\(\max(\lfloor\frac{r}{k}\rfloor-l+1,0)\)。点击查看代码#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;intt,l,r,k;signedmain(){ cin>>t; while(t--){ cin>>l>>r>>k; cout<<max(0ll,......
  • 题解:P11262 [COTS 2018] 题日 Zapatak
    https://www.luogu.com.cn/article/i7ajvm8e哈希好题。题意给定一个序列,每次询问给定两个长度相等的区间,问这两个区间是否只有一个数不一样。思路发现我们要求的信息只与数的出现次数有关,自然想到桶。那么如果有两个区间合法,那这两个区间的桶只有两个位置不同且桶内的值均相......
  • P8162 [JOI 2022 Final] 让我们赢得选举 (Let's Win the Election) 题解
    P8162[JOI2022Final]让我们赢得选举(Let'sWintheElection)题解朴素的想法是先抓一部分人,再一起去发表演讲。这样就要按\(b\)的值从小到大排序,枚举选择的一部分\(b\)值,在后面挑选一些最小的\(a\)选择即可。但这样显然是错误的。观察到\(n\le500\),显然是\(O(n^3......
  • 题解:P11062 【MX-X4-T2】「Jason-1」加法
    一道简单的分讨。思路可分成两种情况。当\(a\)和\(b\)同号时:这种情况,显而易见的是\(|a-b|\)的最小值必定是\(|a|,|b|,|a-b|\)之一。当\(a\)和\(b\)异号时:对\((a,b)\)执行欧几里得算法可以将一个变为\(0\),另一个变为\(\gcd(a,b)\)(忽略正负号)。再将\(0\)变......
  • 题解:P10967 [IOI2000] 邮局(原始版)
    思路首先将坐标排序。定义\(dp_{i,j}\)为前\(i\)个村庄放\(j\)个邮局的前\(i\)个村庄的最小距离总和,\(f(i,j)\)表示村庄区间\([i,j]\)内放一个村庄时该区间的总和。转化式易得\(dp_{i}{j}=dp_{k}{j-1}+f(k+1,i),k\in[0,i)\)。则本题的难点就为求\(f(k-1,i)\)。......
  • 题解:UVA1362 Exploring Pyramids
    思路:显然的,若不是叶子结点都应该至少遍历两次。于是两个相同访问之间就可能是一颗子树。更加具体的,如同\(s_l,\dots,s_k,\dots,s_r\),使得\(s_l=s_k\),那么就可以认为\(s[l,k]\)是\(s[l,r]\)的一颗子树,设区间\(s[l,r]\)的结构数量为\(f_{l,r}\),那么根据乘法原理,当把\(......
  • 241111 noip 题解
    省流:\(100+50+10+30\)。还是不稳定啊,noip上不了270就真的要退役了。T1题意:给定一个长度为\(n\)的序列\(a\),每次你可以交换相邻两个位置,求出最小交换次数以及字典序最小的交换方案使得\(a\)的每个不是本身的前缀都不是排列。\(n\leq10^5\)。注意到每次交换至多会减少一......
  • [题解]P11233 [CSP-S 2024] 染色
    P11233[CSP-S2024]染色设\(f[i][j=0/1]\)表示涂到第\(i\)位,且第\(i\)为颜色为\(j\),则考虑用\(i\)之前能和\(i\)匹配的位置\(p\)进行转移。\(p\)需要满足下面的条件:\(a[p]=a[i]\)。\(p\)的颜色为\(j\)。\([p+1,i-1]\)之间的颜色全不为\(j\)。显然,我们只需要找满足条件的......
  • AT_agc012_f [AGC012F] Prefix Median 题解
    首先将序列排序,这是显然的。考虑倒着确定\(b\)序列中的每个数。即从完整的\(a\)序列开始,每次删掉两个数,记录中位数。先找出\(b\)序列合法的条件。容易发现对于所有\(i\),在\(b_{p_i}\)成为中位数时,\(p_i,p_{i+1}\)之间的所有数都已经被删除了,且\(i\lep_i\le2n-i\)。......