一.题目概括
给出一个合法的一元一次方程,求它的解(注意,方程只包含整数、小写字母及 +
、-
、=
三个数学符号(当然,符号“-
”既可作减号,也可作负号)。方程中没有括号,也没有除号,方程中的字母表示未知数,该方程有唯一解)
输出解方程的结果(精确至小数点后三位)。
二.关键点
1.小学数学
(没有学过解一元一次方程的OIer参考https://zhuanlan.zhihu.com/p/661851542)
一元一次方程的计算在小学五年级有教到,可以总结出以下步骤:
①去分母(通过两边同时乘以所有分母的公倍数,最好是最小公倍数)
②去括号(如果有括号,或去分母后产生括号,那么为了合并同类项先把括号去掉)
③移项(把未知数都移到一边,常数都移到另一边)
④合并同类项(变成ax=b的形式)
⑤系数化为1(方程两边同时除以a,即x=b/a)--引自哔哩哔哩
所以,可以现在纸面上进行筛选和添加
去分母:由于常数全部为整数,所以舍去
去括号:由于无括号,所以舍去
移项:解方程中必须保留(在筛选分类时可以把含有未知数的项移到vector动态数组a,把常数项移到vector动态数组b,就可以被视为移项)
合并同类项:解方程中必须保留
系数化为一:iomanip库函数setprecision(n)可以做到保留n位的效果,保留
但是这里还需要添加一些(毕竟电脑不是人脑)
筛选未知数:将未知数筛选出来,遍历一遍数组即可
分割项:将多项式分割成若干单项式之和,这里可以和移项同步进行
筛选左右两边的数字:即把ax=b中a和b挑选出来
所以可以得到大致思路
输入-->筛选未知数-->分割项并移项-->合并同类项-->输出(同时系数化为1)
2.细节
(1).补数字
类似a+3a=4这一类的方程,可以注意到,‘1’被省略了,所以需要特判
(2).变号
我们默认含有未知数的项在等号左边,常数项在右边,所以当一个项在其所属方向异侧移动时,需要变号
(3)溢出问题
选择在输入字符串后面加入一个字符‘&’
三.AC代码
1.解法1:
字符数组做法和字符串类似,不再展示
#include <iostream>
#include <cstring>
#include <vector>
#include <iomanip>//保留三位浮点数库
using namespace std;
string s,tmp;
int ls,lv0,lv1,flag,num_l,num_r;//lv0:左边数字和,lv1:右边数字和
char ch;
vector<string> vec[2];
char find_ch(){
for(int i=0;i<ls;i++){
if('a'<=s[i]&&s[i]<='z')return s[i];//找到未知数,返回
}
}
void seperate(int ls){
bool flag=false;
bool flaga=false;
for(int i=0;i<ls;i++){
if(s[i]=='=')flaga=true;//左边变成右边
else if(s[i+1]=='+'||s[i+1]=='-'||s[i+1]=='='||s[i+1]=='&'){
tmp.push_back(s[i]);
flag=true;
if(tmp.find(ch)!=string::npos){//该项找到了未知数
if(tmp[0]!='+'&&tmp[0]!='-')tmp='+'+tmp;
if(flaga&&tmp[0]=='-')tmp[0]='+';
else if(flaga&&tmp[0]=='+')tmp[0]='-';
}
else{
if(tmp[0]!='+'&&tmp[0]!='-')tmp='+'+tmp;
if(!flaga&&tmp[0]=='-')tmp[0]='+';
else if(!flaga&&tmp[0]=='+')tmp[0]='-';
}
if(tmp.find(ch)!=string::npos)vec[0].push_back(tmp);
else vec[1].push_back(tmp);
tmp.clear();
}
else if(flag&&s[i]=='+')flag=false;
else if(flag&&s[i]=='-'){
tmp.push_back(s[i]);
flag=false;
}
else tmp.push_back(s[i]);
}
return;
}
int main(){
cin>>s;
s.push_back('&');//防止溢出,见第20行代码
ls=s.length();
ch=find_ch();
seperate(ls);
lv0=vec[0].size();
lv1=vec[1].size();
for(int i=0;i<lv0;i++){
string v=vec[0][i];
int t=0;
for(int j=0;j<v.length();j++){
if('0'<=v[j]&&v[j]<='9')t=t*10+(v[j]-'0');//构造数字
else continue;
}
if(v[0]=='-')t*=(-1);//负数变号
if(t==0)t=1;
num_l+=t;
}
for(int i=0;i<lv1;i++){
string v=vec[1][i];
int t=0;
for(int j=0;j<v.length();j++){
if('0'<=v[j]&&v[j]<='9')t=t*10+(v[j]-'0');
else continue;
}
if(v[0]=='-')t*=(-1);
num_r+=t;
}
cout<<ch<<'=';
cout<<fixed<<setprecision(3)<<num_r/(num_l*1.00);//保留三位输出
}
时间: