题目描述
做化学题时,小 F 总是里算错相对分子质量,这让他非常苦恼。
小 F 找到了你,请你来帮他算一算给定物质的相对分子质量。
如果你没有学过相关内容也没有关系,你可以从样例和提示里理解该题所求内容。
输入输出格式
输入格式:
输入一行,为一个长度为 LL (L\leq 100)(L≤100) 的不含空格的字符串,表示给定物质的化学式。
化学式仅包括以下内容:
- 元素:如
Au
(金),Hf
(铪),出现的所有元素及其相对原子质量以附表为准。 - 下标
_{}
:表示某个原子、离子或者原子团的个数,如H_{2}O
表示 H_2OH2O (水),C_{60}
表示 C_{60}C60 (足球烯)。 - 括号
()
:表示一个原子团,下标对团内物质生效。如Ca(OH)_{2}
表示 Ca(OH)_2Ca(OH)2 (熟石灰)。 - 水合物
~
:如CuSO_{4}~5H_{2}O
表示 CuSO_4 \cdot 5H_2OCuSO4⋅5H2O(胆矾)。水之前如果存在数字,保证一定是大于 22 的正整数,如果省略该部分则默认为 11 。如上述胆矾中,表示水的个数的5
。
形式化地讲,你处理的化学式满足以下规则:
分子
~
数量H_{2}O
其中数量或水合部分可省。
对于分子,满足:
部分
_{
数量}
部分_{
数量}
...部分_{
数量}
其中数量可省。
对于每个“部分”(原子,原子团,离子……),满足:
元素
或
(
元素_{
数量}
元素_{
数量}
... 元素_{
数量})
其中数量可省。
请注意,满足上述条件的化学式不会出现括号嵌套;上文中出现的 “数量” 所指代的数字不超过 1000010000。
好久之前的一道题,SB到不能再SB的模拟,按题意进行模拟即可
然而还是调了半天,错误的原因还是我把Au的相对原子质量记错了以及忘打Zn了。。
把代码给gay神调之前,我信誓旦旦:我相对原子质量倒背如流
真香~
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 int now,len,num; 6 double ans; 7 char S[1010]; 8 double get() 9 { 10 if(S[now]=='A') 11 { 12 now++; 13 if(S[now]=='l') {now++;return 27;} 14 if(S[now]=='g') {now++;return 108;} 15 if(S[now]=='u') {now++;return 197;} 16 } 17 else if(S[now]=='B') {now++;return 137;} 18 else if(S[now]=='C') 19 { 20 now++; 21 if(S[now]=='a') {now++;return 40;} 22 if(S[now]=='l') {now++;return 35.5;} 23 if(S[now]=='u') {now++;return 64;} 24 return 12; 25 } 26 else if(S[now]=='F') 27 { 28 now++; 29 if(S[now]=='e') {now++;return 56;} 30 return 19; 31 } 32 else if(S[now]=='H') 33 { 34 now++; 35 if(S[now]=='f') {now++;return 178.5;} 36 if(S[now]=='g') {now++;return 201;} 37 return 1; 38 } 39 else if(S[now]=='I') {now++;return 127;} 40 else if(S[now]=='K') {now++;return 39;} 41 else if(S[now]=='M') 42 { 43 now++; 44 if(S[now]=='g') {now++;return 24;} 45 if(S[now]=='n') {now++;return 55;} 46 } 47 else if(S[now]=='N') 48 { 49 now++; 50 if(S[now]=='a') {now++;return 23;} 51 return 14; 52 } 53 else if(S[now]=='O') {now++;return 16;} 54 else if(S[now]=='P') 55 { 56 now++; 57 if(S[now]=='t') {now++;return 195;} 58 return 31; 59 } 60 else if(S[now]=='S') 61 { 62 now++; 63 if(S[now]=='i') {now++;return 28;} 64 return 32; 65 } 66 else if(S[now]=='Z') {now++;return 65;} 67 } 68 int getnum() 69 { 70 int x=0; 71 while(S[now]!='{') now++; 72 now++; 73 while(S[now]!='}') x=x*10+S[now]-'0',now++; 74 now++; 75 return x; 76 } 77 int getwater() 78 { 79 int x=0; now++; 80 while(S[now]!='H') x=x*10+S[now]-'0',now++; 81 while(S[now]!='O') now++; 82 if(!x) x++; 83 now++; 84 return x*18; 85 } 86 void work() 87 { 88 int x=0; 89 double tot=0,last=0; 90 now++; 91 while(S[now]!=')') 92 { 93 if(S[now]>='A'&&S[now]<='Z') tot+=last,last=get(); 94 else if(S[now]>='a'&&S[now]<='z') now++; 95 else if(S[now]=='_') num=getnum(),tot+=num*last,last=0; 96 else if(S[now]=='~') tot+=last,last=0,tot+=getwater(); 97 } 98 tot+=last; 99 while(S[now]!='{') now++; 100 now++; 101 while(S[now]!='}') x=x*10+S[now]-'0',now++; 102 now++; 103 ans+=(double)x*tot; 104 } 105 int main() 106 { 107 scanf("%s",S); 108 len=strlen(S); 109 S[len]='&'; 110 double last=0; 111 while(now!=len) 112 { 113 if(S[now]=='(') ans+=last,last=0,work(); 114 else if(S[now]>='A'&&S[now]<='Z') ans+=last,last=get(); 115 else if(S[now]>='a'&&S[now]<='z') now++; 116 else if(S[now]=='_') num=getnum(),ans+=num*last,last=0; 117 else if(S[now]=='~') ans+=last,last=0,ans+=getwater(); 118 } 119 cout<<ans+last; 120 return 0; 121 } 122 //KAl(SiO_{4})_{2}~12H_{2}