P4711【化学】 相对分子质量 简单题解
本蒟蒻写的第一道大模拟题(我们机房某巨佬说是中模拟)
我:“ A了这道题,妈妈再也不同担心我算不对相对分子质量啦~ ”
思路
做这种模拟题时,需要一个明确的思路。
我们在开始之前,先来研究一下这些化学式。
这些化学式,由小括号,大括号,下划线,数字,化学元素组成。
看到这些,是不是觉得无从下手?是不是尝试去实现了但是实现不了?
别着急,慢慢来。
我们先讨论单个的元素。eg:
对于单个的元素,我们只需要预先将这些元素与他们的相对原子质量存好,用的时候调出来就可以了。对于这个,我们可以用一个map实现(STL大法好)。
更具体的,map应该这样定义:map<string,double> (具体的待会可以看看代码)
好,单个元素讲完了,现在我们来讨论没有原子团且有一个元素有下标的化学物质。 eg:
首先,我们需要一个
接下来,如果检测到元素,并且该元素的下一位不是下划线,答案加上该元素的相对原子质量。否则启动
有下标的化学元素解决啦,下面开始讨论带有原子团的化学式。
哎,带有小括号的喔,怎么玩啊?(之前就是在这里卡了半天)
别慌,我们来试着把整个化学式括起来。
这个时候我们可以很容易的发现,对于带括号的,我们只需要单独解决括号里面的内容就行了。怎么解决?当然是递归啦~。因为括号里面的内容都还是原子团或者化学式。
最后剩下的是带水的化学式,我们单独处理它。首先读入的时候寻找水分子连接符 “~” ,再将它后面的数字读入就可以了,如果没有数字,默认为 1 。
友情提示:建议除了游标使用整型变量,其他的运算都要用 double 类型。
代码
接下来是大家最喜欢的代码~
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<queue>
#include<map>
#define ll long long
using namespace std;
map<string,double> app;
double ans;
string elememts[26]={"H","C","N","O","F","Na","Mg","Al","Si","P","S","Cl","K","Ca","Mn","Fe","Cu","Zn","Ag","I","Ba","Hf","Pt","Au","Hg"};
string s;
void init_elements()
{
for(int i=0;i<25;++i) //这样有点小麻烦了
{
if(i==0) app[elememts[i]]=1;
if(i==1) app[elememts[i]]=12;
if(i==2) app[elememts[i]]=14;
if(i==3) app[elememts[i]]=16;
if(i==4) app[elememts[i]]=19;
if(i==5) app[elememts[i]]=23;
if(i==6) app[elememts[i]]=24;
if(i==7) app[elememts[i]]=27;
if(i==8) app[elememts[i]]=28;
if(i==9) app[elememts[i]]=31;
if(i==10) app[elememts[i]]=32;
if(i==11) app[elememts[i]]=35.5;
if(i==12) app[elememts[i]]=39;
if(i==13) app[elememts[i]]=40;
if(i==14) app[elememts[i]]=55;
if(i==15) app[elememts[i]]=56;
if(i==16) app[elememts[i]]=64;
if(i==17) app[elememts[i]]=65;
if(i==18) app[elememts[i]]=108;
if(i==19) app[elememts[i]]=127;
if(i==20) app[elememts[i]]=137;
if(i==21) app[elememts[i]]=178.5;
if(i==22) app[elememts[i]]=195;
if(i==23) app[elememts[i]]=197;
if(i==24) app[elememts[i]]=201;
}
}
double water(int l,int r)
{
int i=l+1,num=0;
while(s[i]>='0'&&s[i]<='9')
{
num=num*10+s[i]-'0';
i++;
}
if(num==0) return 18;
return num*18;
}
double answer(int l,int r)
{
int i=l;
double now=0,last=0;
while(i<=r)
{
if(s[i]>='A'&&s[i]<='Z')
{
if(s[i+1]>='a'&&s[i+1]<='z')
{
if(s[i+2]!='_')
{
string str;
str+=s[i];
str+=s[i+1];
now+=app[str];
i+=2;
}
else
{
string str;
str+=s[i];
str+=s[i+1];
now+=app[str];
last=app[str];
i+=2;
}
}
else
{
if(s[i+1]!='_')
{
string str;
str=s[i];
now+=app[str];
i++;
}
else
{
string str;
str=s[i];
now+=app[str];
last=app[str];
i++;
}
}
}
if(s[i]=='(')
{
int j;
for(j=i+1;j<s.size();++j)
{
if(s[j]==')') break;
}
double t=answer(i+1,j-1);
i=j+1;
if(s[i]=='_')
{
last=t;
}
now+=t;
}
if(s[i]=='_')
{
if(last==0)
{
string str2;
str2=s[i-1];
i+=2;
int num=0;
while(s[i]!='}')
{
num=num*10+s[i]-'0';
i++;
}
now+=(num-1)*app[str2];
}
else
{
int num=0;
i+=2;
//cout<<s[i]<<" ";
while(s[i]!='}')
{
num=num*10+s[i]-'0';
i++;
}
now+=(num-1)*last;
}
i++;
}
if(s[i]=='~') return now;
}
return now;
}
int main()
{
init_elements(); //化学元素初始化
cin>>s;
ans=answer(0,s.size()-1);
int t=s.find('~',0);
if(t!=s.npos) ans+=water(t,s.size()-1);
cout<<ans<<endl;
return 0;
}