题目背景
NCLNCL 是一家专门从事计算器改良与升级的实验室,最近该实验室收到了某公司所委托的一个任务:需要在该公司某型号的计算器上加上解一元一次方程的功能。实验室将这个任务交给了一个刚进入的新手ZL先生。
题目描述
为了很好的完成这个任务, ZLZL 先生首先研究了一些一元一次方程的实例:
4+3x=84+3x=8
6a-5+1=2-2a6a−5+1=2−2a
-5+12y=0−5+12y=0
ZLZL 先生被主管告之,在计算器上键入的一个一元一次方程中,只包含整数、小写字母及+、-、=这三个数学符号(当然,符号“-”既可作减号,也可作负号)。方程中并没有括号,也没有除号,方程中的字母表示未知数。
你可假设对键入的方程的正确性的判断是由另一个程序员在做,或者说可认为键入的一元一次方程均为合法的,且有唯一实数解。
输入输出格式
输入格式:
一个一元一次方程。
输出格式:
解方程的结果(精确至小数点后三位)。
输入输出样例
输入样例#1: 复制
6a-5+1=2-2a
输出样例#1: 复制
a=0.750
思路:getchar()输入防止TCL
等式变换分别求出变量系数值以及常量值,后者除以前者得到结果、
存在很多细节的地方(看代码注释)
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll; //防止数据溢出
int main()
{
ll local_judge=1;
ll pos_judge=1;
ll count=0;
ll deno=0;
ll ans=0;
double result;
char x;
bool sym_judge=false;
char s=getchar();
while(1)
{
if(s>='a' && s<='z') //找到未知变量
{
x=s;
if(count==0 && !sym_judge) //判断未知变量前面是否有系数
{
deno += pos_judge * local_judge; //默认系数为1
}
else
{
deno += pos_judge * local_judge *count; //等式变换求变量的系数值
count=0;
pos_judge=1;
sym_judge=false;
}
}
else if(s=='-')
{
ans += -count * pos_judge * local_judge;
sym_judge=false;
count=0;
pos_judge=-1; //遇到'-',pos_judge标记-1
}
else if(s=='+')
{
ans += -count * pos_judge * local_judge;
sym_judge=false;
count=0;
pos_judge=1; //遇到'+',pos_judge标记1
}
else if(s=='=')
{
ans += -count * pos_judge *local_judge;
sym_judge=false;
count=0;
pos_judge=1; //遇到'+',pos_judge标记1
local_judge=-1; //local_judge标记等式右边
}
else if(s>='0' && s<='9')
{
count = count*10+s-'0'; //记录完整数值
sym_judge=true;
}
else
{
ans +=-count*pos_judge*local_judge; //最后一个是数值也不能漏掉
break;
}
s=getchar();
}
result=double(ans)/deno;
printf("%c=%.3lf",x,result==0?abs(result):result); //c++中0除以任何数得-0,强制转换为0
return 0;
}
下面是转发一位大佬详细的代码注释及其源代码:
(可以参考学习)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;//以防万一用long long
char x; ll coe,value,opp=1;//coe表示系数,value表示值,opp表示在等号左边还是右边
double ans;
int main(){
char c=getchar();//为了节省空间当然要在线
ll cur=0,sign=1; bool value_gotten=false;//cur为当前读入的数值,sign表示当前数值符号,value_gotten是一个标记变量,字面意思是是否读入过数值,用途下面说
while (true){
if (c>='a' && c<='z'){
x=c; if (cur==0 && !value_gotten) coe+=opp*sign,value_gotten=false; //这也是个坑点(虽然数据没有涉及),如果cur为0又读入了变量名称有两种情况:一时+0x或-0x,另一种是默认系数为1,value_gotten专门判断这两种情况
else coe+=opp*sign*cur,cur=0,sign=1,value_gotten=false;
}
else if (c=='-') value+=-opp*sign*cur,cur=0,sign=-1,value_gotten=false;//如果是减号把当前数值加入值(如果之前是变量则当前数值为0,加入也没有影响),并清空当前数值,设value_gotten为false,符号修改为负
else if (c=='+') value+=-opp*sign*cur,cur=0,sign=1,value_gotten=false;//加号和减号一样,只是把符号修改为正
else if (c>='0' && c<='9') cur=cur*10+c-'0',value_gotten=true;//如果是数字,就对cur进行计算,并把value_gotten设为true
else if (c=='=') value+=-opp*sign*cur,cur=0,sign=1,opp=-opp,value_gotten=false;//等号和加减号差不多,只是要把opp设为负
else {value+=-opp*sign*cur;break;}//最后的值累加上去
c=getchar();
}
ans=double(value)/coe;//计算ans
printf("%c=%.3lf",x,ans==0?abs(ans):ans);//这涉及一个很坑的地方:C++里0除以一个负数值为-0,专门避免这种情况
return 0;
}