首先,我们自然而然联想到表达式求值的一道题,只要将元素符号转化为数字,再在分子式内加上加号和乘号就可以了。当然,这样做肯定费时费力,所以我们将那道题目的栈结构改变一下。
几个元素符号看着很不顺眼,所以我们将他们转化成值,即首位和末位按权展开:
xxxxxxxxxxfunction hash(s:string):longint;beginif length(s)=1 then exit(ord(s[1])-64)else exit((ord(s[1])-64)*100+ord(s[2])-96);end;
读入部分很简单
xxxxxxxxxxwhile true dobeginreadln(st);if st='END_OF_FIRST_PART' then break;//结束了就退出k:=pos(' ',st);val(copy(st,k+1,length(st)),m);//数字部分mass[hash(copy(st,1,k-1))]:=m;//定义原子质量end;
然后,正文部分如何展开呢?
我们有如下步骤:
第一步,如果遇到左括号,直接进栈,等级
第二步,如果遇到大写字母,向后寻找还有没有小写字母和数字,并得到这些东西。
第三步,如果遇到右括号,向后寻找还有没有数字,并得到这些东西。
然后出栈。
值得注意的是,如果得不到数字,则
xxxxxxxxxxwhile true dobeginreadln(st);fillchar(num,sizeof(num),0);//初始化w:=0;//当前级别if st='0' then break;//完成了就退出flag:=true;st:='('+st+')';//方便最后的处理for i:=1 to length(st) dobeginif st[i]='(' then//进栈begininc(w);num[w]:=0;end;if st[i] in ['A'..'Z'] then//碰到元素符号beginif st[i+1] in ['a'..'z'] then name:=st[i]+st[i+1]else name:=st[i];//得到完整名称if mass[hash(name)]=-1 then//如果找不到这个元素符号beginwriteln('UNKNOWN');flag:=false;break;end;j:=i+length(name);//继续向后寻找数字cnt:=0;while st[j] in ['0'..'9'] dobegincnt:=cnt*10+ord(st[j])-48;//和C++的快读差不多inc(j);end;if cnt=0 then cnt:=1;//如果没有数字就是1num[w]:=num[w]+mass[hash(name)]*cnt;//获得整个部分的质量分数end;if st[i]=')' then//出栈beginj:=i+1;//向后寻找数字cnt:=0;while st[j] in ['0'..'9'] dobegincnt:=cnt*10+ord(st[j])-48;inc(j);end;if cnt=0 then cnt:=1;dec(w);//更新上一级别的质量分数num[w]:=num[w]+num[w+1]*cnt;end;end;if flag=true then writeln(num[0]);//如果没有出现UNKNOWN情况end;
xxxxxxxxxxvar mass,num:array[0..10000]of longint;st,name:string;flag:boolean;k,i,j,cnt,w,m:longint;function hash(s:string):longint;beginif length(s)=1 then exit(ord(s[1])-64)else exit((ord(s[1])-64)*100+ord(s[2])-96);end;beginfillchar(mass,sizeof(mass),255);while true dobeginreadln(st);if st='END_OF_FIRST_PART' then break;k:=pos(' ',st);val(copy(st,k+1,length(st)),m);mass[hash(copy(st,1,k-1))]:=m;end;while true dobeginreadln(st);fillchar(num,sizeof(num),0);w:=0;if st='0' then break;flag:=true;st:='('+st+')';for i:=1 to length(st) dobeginif st[i]='(' thenbegininc(w);num[w]:=0;end;if st[i] in ['A'..'Z'] thenbeginif st[i+1] in ['a'..'z'] then name:=st[i]+st[i+1]else name:=st[i];if mass[hash(name)]=-1 thenbeginwriteln('UNKNOWN');flag:=false;break;end;j:=i+length(name);cnt:=0;while st[j] in ['0'..'9'] dobegincnt:=cnt*10+ord(st[j])-48;inc(j);end;if cnt=0 then cnt:=1;num[w]:=num[w]+mass[hash(name)]*cnt;end;if st[i]=')' thenbeginj:=i+1;cnt:=0;while st[j] in ['0'..'9'] dobegincnt:=cnt*10+ord(st[j])-48;inc(j);end;if cnt=0 then cnt:=1;dec(w);num[w]:=num[w]+num[w+1]*cnt;end;end;if flag=true then writeln(num[0]);end;end.