题解:「化学」相对分子质量
small_lemon_qwq
·
2025-05-29 13:30:31
·
题解
\colorbox{orange}{\color{white}\texttt{题目传送门}}
考虑我们人工计算相对分子质量是怎么算的。
以样例 3 为例,假设我们不知道每个元素的相对元素质量,那么我们可以列出算式:
\operatorname{Mr}(\mathrm{Ca(OH)_2})=\operatorname{Ar}(\mathrm{Ca})+(\operatorname{Ar}(\mathrm{O})+\operatorname{Ar}(\mathrm{H}))\times2
不难发现 \operatorname{Ar}() 不影响我们做题,忽略掉:
\operatorname{Mr}(\mathrm{Ca(OH)_2})=\mathrm{Ca}+(\mathrm{O}+\mathrm{H})\times2
那么我们如果能在程序里实现列出这个算式这个问题就变成了:
将每个元素替换为它对应的相对原子质量
计算表达式值。
步骤 1 显然可以用正则表达式做,表达式:
单元素正则表达式(以 \mathrm{S} 为例):s=regex_replace(s,regex("S([^a-z])"),"127$1"),这里表示将所有 S 加上一个非小写字母字符的子串替换为 127 加上这个非小写字母字符,非小写字母字符是为了防止错误的替换 Si,但是这样就需要再整个字符串后面加入一个特殊字符。
双元素正则表达式(以 \mathrm{Si} 为例):s=regex_replace(s,regex("Si"),to_string(28)),表示将所有 Si 子串替换为 28。
现在的问题就是如何列出这个算式了。
首先忽略掉 ~[数字]H_{2}O,用正则表达式:string s1=regex_replace(s,regex(".*?(~(\\d*?H_\\{2\\}O))?$"),"$2"); 和 string s2=regex_replace(s,regex("(.*?)(~(\\d*?H_\\{2\\}O))?$"),"$1");,其中 s1 表示 ~[数字]H_{2}O 部分,s2 表示除去 ~[数字]H_{2}O 的部分。
接下来观察分子部分。
题目末尾有这样一句话:
下标相当于乘。
直接将下标变为乘号。:string s3=regex_replace(s2,regex("_\\{(\\d*?)\\}"),"*$1");,括号不用处理,只需要处理加号了。
可以直接在每个元素开头加上一个加号,但是对于样例 3 就会变成这样:+Ca(+O+H)*2,所以需要处理一下,在括号前也加入加好,如果一个元素之前没有字符或者是括号就不加入加好。
由于正则表达式不会重复匹配,所以这部分只能手写:
string s4;
char c1='(';
for(char c:s3){
if(c>='A'&&c<='Z'&&c1!='('||c=='('){
s4+="+";
}
s4+=(c1=c);
}
最后就是愉快的表达式计算了,如果用 python 可以用 eval 函数,C++ 就只能手写了。
#include
using namespace std;
#define int long long
#define $(x,y) s4=regex_replace(s4,regex(string(1,x)+"([^a-z])"),to_string((int)(y*2))+"$1")
#define $$(x,y) s4=regex_replace(s4,regex(x),to_string((int)(y*2)))
string s;
map
int calc(string s){
string b;
stack
stack
int x=0;
s="("+s+")";
for(char c:s){
if(c=='('){
st.push('(');
}else if(c=='+'||c=='*'){
if(x)b+=to_string(x)+" ";
x=0;
while(st.size()&&mp[st.top()]>=mp[c]){
b+=st.top()+(string)" ";
st.pop();
}
st.push(c);
}else if(c==')'){
if(x)b+=to_string(x)+" ";
x=0;
while(st.size()&&st.top()!='('){
b+=st.top()+(string)" ";
st.pop();
}
if(st.size())st.pop();
}else if(isdigit(c)){
x=x*10+c-'0';
}
}
x=0;
for(char c:b){
if(isdigit(c)){
x=x*10+c-'0';
}else if(c==' '){
if(x)st2.push(x);
x=0;
}else if((c=='+'||c=='*')&&st2.size()>=2){
int tp2=st2.top();st2.pop();
int tp1=st2.top();st2.pop();
if(c=='+')st2.push(tp1+tp2);
if(c=='*')st2.push(tp1*tp2);
}
}
if(!st2.size())return 0;
return st2.top();
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
mp['(']=1;
mp['+']=2;
mp['*']=3;
cin>>s;
string s1=regex_replace(s,regex(".*?(~(\\d*?H_\\{2\\}O))?$"),"$2");
string s2=regex_replace(s,regex("(.*?)(~(\\d*?H_\\{2\\}O))?$"),"$1");
string s3=regex_replace(s2,regex("_\\{(\\d*?)\\}"),"*$1");
// cout< string s4; char c1='('; for(char c:s3){ if(c>='A'&&c<='Z'&&c1!='('||c=='('){ s4+="+"; } s4+=(c1=c); } if(!s1.empty()){ int t=max(stoll(string("0")+regex_replace(s1,regex("(\\d*?)H.+"),"$1")),1ll); s4+="+"+to_string(t)+"*(H*2+O)"; } s4+=" "; $('H',1); $('C',12); $('N',14); $('O',16); $('F',19); $$("Na",23); $$("Mg",24); $$("Al",27); $$("Si",28); $('P',31); $('S',32); $$("Cl",35.5); $('K',39); $$("Ca",40); $$("Mn",55); $$("Fe",56); $$("Cu",64); $$("Zn",65); $$("Ag",108); $('I',127); $$("Ba",137); $$("Hf",178.5); $$("Pt",195); $$("Au",197); $$("Hg",201); int t=calc(s4); // cout< cout< if(t%2)cout<<".5"; return 0; }