B 分子
题目描述 在遥远的斯卡布罗集市,有机分子只能由 C, H, O 三种元素组成。根据珂学家们的探测,一个 C 原子的式量为 13 ,一个 H 原子的式量为 1 ,一个 O 原子的式量为 17 。一个有机分子的式量恰为各个原子的式量的总和。对于有机分子式给出如下定义:有机分子式只可能包含数字、括号和 C, H, O 三种元素标记;数字只能出现在元素标记或右括号的右边,代表该元素(或括号内的分子式)重复出现的次数;数字只可以是不包含前导零的正整数;如果一个元素右侧没有数字,那么表示该元素只出现一次;括号内包含非空的有机分子式,但该有机分子式不再嵌套括号。例如 (HH)3H(H)、CO2、CH12、CHHOO 都是合法的有机分子式。而 4HC、CHTHOLLOY、CH3(CH2)3(CH(CHCH3)2CH3)2(CH2)3CH3 都不是合法的有机分子式。对于符合上述要求的分子式,你能帮助珂学家们计算它的分子式量吗?
输入描述 输入仅一行,包含一个字符串,代表分子式。保证符合上述定义,字符串中不含除 C, H ,O,括号和数字以外的字符,且长度不超过 10^5
输出描述 在一行中输出一个整数,代表该分子的式量。保证答案不超过 10^15。
思路
我原本还以为这道题和栈的经典应用题型“解析计算式”相近,没想到这题还更简单,因为题目里说了没有嵌套括号,所以这题都不用开栈。
考虑把括号内的权重单独算,然后把整个括号看作一个整体元素,那么这题所给的分子式实际上就是由 元素 + 数量
的格式文本拼凑而成的。因此,我们每读入一个“元素”,就判断它后面是数字还是另一个元素符号,如果是数字,就读取这个数字,然后对应调整ans即可。
特别的,如果当前是在括号内,那么我们不能直接调整ans,而是要单独加到一个临时int变量中,直到遇到一个 ) 字符,再看 ) 字符后是数字还是其他符号。如果是数字,要把整个括号内的权重拿出来乘上这个数字加入ans,否则直接加到ans就行了。记得处理完后把这个临时int变量置零就好。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cmath>
#include<iostream>
#include<cstring>
using namespace std;
template<class _T>inline void read(_T &_a)
{
bool f=0; char _c=getchar(); _a=0;
while(_c<'0'||_c>'9'){ if(_c=='-') f=1; _c=getchar(); }
while(_c>='0'&&_c<='9'){ _a=(_a<<3)+(_a<<1)-'0'+_c; _c=getchar(); }
if(f) _a=-_a;
}
const int MAXN=1000002;
char str[MAXN];
int n;
long long ans,tmpkh,tmpqz; // tmpkh临时储存了当前括号内的值,tmpqz用于读取数字。
bool inkh; // 在括号内
inline long long rd(int pos)
{
long long _a=0;
char _c=str[pos++];
while(_c<'0'||_c>'9') _c=str[pos++];
while(_c>='0'&&_c<='9'){ _a=(_a<<3)+(_a<<1)-'0'+_c; _c=str[pos++]; }
return _a;
}
int main()
{
scanf("%s",str+1);
n=strlen(str+1);
for (int i=1;i<=n;++i)
{
if(str[i]=='(')
{
inkh=true;
continue;
}
if(str[i]==')')
{
inkh=false;
if(str[i+1]>='0'&&str[i+1]<='9')
{
tmpqz=rd(i+1);
ans+=tmpkh*tmpqz;
while(str[i+1]>='0'&&str[i+1]<='9') ++i;
tmpkh=0;
continue;
} else {
ans+=tmpkh;
tmpkh=0;
continue;
}
}
if(str[i]=='C')
{
if(inkh)
{
if(str[i+1]>='0'&&str[i+1]<='9')
{
tmpqz=rd(i+1);
tmpkh+=13*tmpqz;
while(str[i+1]>='0'&&str[i+1]<='9') ++i;
continue;
} else {
tmpkh+=13;
continue;
}
} else {
if(str[i+1]>='0'&&str[i+1]<='9')
{
tmpqz=rd(i+1);
ans+=13*tmpqz;
while(str[i+1]>='0'&&str[i+1]<='9') ++i;
continue;
} else {
ans+=13;
continue;
}
}
}
if(str[i]=='H')
{
if(inkh)
{
if(str[i+1]>='0'&&str[i+1]<='9')
{
tmpqz=rd(i+1);
tmpkh+=tmpqz;
while(str[i+1]>='0'&&str[i+1]<='9') ++i;
continue;
} else {
tmpkh+=1;
continue;
}
} else {
if(str[i+1]>='0'&&str[i+1]<='9')
{
tmpqz=rd(i+1);
ans+=tmpqz;
while(str[i+1]>='0'&&str[i+1]<='9') ++i;
continue;
} else {
ans+=1;
continue;
}
}
}
if(str[i]=='O')
{
if(inkh)
{
if(str[i+1]>='0'&&str[i+1]<='9')
{
tmpqz=rd(i+1);
tmpkh+=17*tmpqz;
while(str[i+1]>='0'&&str[i+1]<='9') ++i;
continue;
} else {
tmpkh+=17;
continue;
}
} else {
if(str[i+1]>='0'&&str[i+1]<='9')
{
tmpqz=rd(i+1);
ans+=17*tmpqz;
while(str[i+1]>='0'&&str[i+1]<='9') ++i;
continue;
} else {
ans+=17;
continue;
}
}
}
}
printf("%lld",ans);
return 0;
}