比较复杂且细节的模拟题

题目描述
在遥远的斯卡布罗集市,有机分子只能由 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^510
5

输出描述:
在一行中输出一个整数,代表该分子的式量。

保证答案不超过 10^{15}10
15

示例1
输入
复制
CH3COOH
输出
复制
64
示例2
输入
复制
CH3(CH2)10CH3
输出
复制
182
示例3
输入
复制
H(HH)C(CH2)3O(H)1
输出
复制
79
备注:
斯卡布罗集市是一个魔法集市,所以对化学的定义可能和麻瓜世界略有不同。

在第二个样例中,一共出现了 12 个C和 26 个H;

在第三个样例中出现了 4 个 C、10 个 H 和 1 个 O。

对于部分编程语言,请注意使用合适的数据类型以避免答案溢出。

题目分析

这个题目我想了蛮久还是没做出来,虽说是看了大佬的代码之后才做出来的,但是还是要大大的称赞这个题目,这个题目很复杂而且需要多次细节处理

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
char c[maxn];
typedef long long ll;
int solve(char c) //判断字母返回对应的值
{
    if (c == 'C')
        return 13;
    else if (c == 'H')
        return 1;
    return 17;
}
int main()
{
    ll ans = 0, sum = 0;
    int flag = 0;
    scanf("%s", c);
    int lc = strlen(c);
    for (int i = 0; i < lc; ++i)
    {
        char x = c[i];
        if (x == '(')
        {
            flag = 1; //标记一次
            ans = 0;  //清空为后续多次出现括号做好准备
            continue;
        }
        if (isalpha(x)) //如果当前这个是字母
        {
            ll num = 1;                          //如果后续没有数字,默认乘以1,因为1在表达式中是不会写出来的
            if (i + 1 < lc && isdigit(c[i + 1])) //判断范围和数字
            {
                num = 0;
                while (i + 1 < lc && isdigit(c[i + 1]))
                    num = num * 10 + (c[++i] - '0');
            }
            if (flag) //如果之前出现过括号那么就是小括号里面的符号需要单独计算
                ans += num * solve(x);
            else
                sum += num * solve(x);
        }
        else //如果不是字母那么一定是右括号,因为之前出现过左括号,不可能是数字,因为数字已经在字母后面计算了
        {
            if (i + 1 < lc && isdigit(c[i + 1]))
            {
                ll num = 0;
                while (i + 1 < lc && isdigit(c[i + 1]))
                    num = num * 10 + (c[++i] - '0');
                ans *= num;//单独计算小括号里面的值
            }
            sum += ans;
            flag = 0;//除去标记继续下一次查找
        }
    }
    printf("%lld\n", sum);
}