首页 > 其他分享 >【题解】Luogu[P4711] 「化学」相对分子质量

【题解】Luogu[P4711] 「化学」相对分子质量

时间:2023-07-29 13:33:07浏览次数:43  
标签:string 题解 double 括号 扫到 P4711 质量 str Luogu

Link

一道简单的模拟题,评绿可能有点高了。

因为没有括号嵌套,难度瞬间降了一个档次,我们直接对着化学式扫一遍即可。

若扫到左括号,说明接下来都是在括号内的,我们标记一下。

若扫到大写字母,说明出现了一个新的元素,那么我们就看后面是否有下标,若有则类似于快读的方式直接处理后面的数字,然后计算当前元素的相对质量。若此时这个元素不在括号内,那么我们直接加入到总答案中;若在括号内,那么接着计算括号内的元素相对质量的总和。

若扫到大括号,则用之前同样的方法计算大括号的下标,用之前记录的括号内元素相对质量总和乘上下标,再计入总答案中。

若扫到 ~,说明后面有个水合物,我们可以直接看水之前是否存在数字,若存在,用之前的方法算出数量,若不存在,数量默认为 \(1\)。然后直接拿水的相对分子质量 \(18\) 乘以水的质量,加到总答案中。我们知道水合物后面一定没有东西了,于是我们可以在计算完水合物后直接结束循环,最后输出答案即可。

需要注意的是在扫的过程中对当前下标位置的细节处理,这里容易出错。

#include <bits/stdc++.h>
using namespace std;
string str;
int n;
double ans;
map< string, double > m;
void init() {
    m["H"] = 1, m["C"] = 12, m["N"] = 14, m["O"] = 16, m["F"] = 19, m["Na"] = 23, m["Mg"] = 24, m["Al"] = 27, m["Si"] = 28, m["P"] = 31, m["S"] = 32, m["Cl"] = 35.5, m["K"] = 39, m["Ca"] = 40, m["Mn"] = 55, m["Fe"] = 56, m["Cu"] = 64, m["Zn"] = 65, m["Ag"] = 108, m["I"] = 127, m["Ba"] = 137, m["Hf"] = 178.5, m["Pt"] = 195, m["Au"] = 197, m["Hg"] = 201;
}
bool isNum(char ch) { return ('0' <= ch && ch <= '9'); }
bool isCaps(char ch) { return ('A' <= ch && ch <= 'Z'); }
bool uisCaps(char ch) { return ('a' <= ch && ch <= 'z'); }
int getNum(int &i) {
    int res = 0;
    while(i <= n && isNum(str[i])) res = res * 10 + (str[i] - '0'), ++i;
    return res;
}
int main() {
    cin >> str, n = str.size(), str = "?" + str, init();
    int num = 0; double res = 0; string a; bool isf = false;
    for(int i = 1; i <= n; ++i) {
        num = 0, a.clear();
        if(str[i] == '(') isf = true;
        if(isCaps(str[i])) {
            a += str[i];
            while(i + 1 <= n && uisCaps(str[i + 1])) ++i, a += str[i];
            if(str[i + 1] == '_') i += 3, num = getNum(i);
            else num = 1;
            res += m[a] * (double)num;
            if(!isf) ans += res, res = 0;
            num = 0;
        }
        if(str[i] == ')') i += 3, num = getNum(i), res *= (double)num, ans += res, res = num = 0, isf = false;
        if(str[i] == '~') {
            ++i, num = 0;
            if(isNum(str[i])) num = getNum(i);
            else num = 1;
            ans += (double)num * 18.0; break;
        }
    }
    cout << ans << endl;
    return 0;
}

标签:string,题解,double,括号,扫到,P4711,质量,str,Luogu
From: https://www.cnblogs.com/agrumestly/p/17589686.html

相关文章

  • [USACO13DEC] The Bessie Shuffle S 洗牌 题解
    提供一种思路,可以做到\(O(n)\)。目前是全OJ最优解,跑到了79ms。update2023.07.29完工,期望无bug(暑假快乐吖o( ̄▽ ̄)ブ)update2023.07.27(要原题检测了,先占个坑,有时间再补)原题大意P3095[USACO13DEC]TheBessieShuffleS有\(n\)张牌,每次取出\(m\;(m<n)\)张牌进行置换操作。操......
  • CF858C 题解
    洛谷链接&CF链接本篇题解为此题较简单做法及较少码量,并且码风优良,请放心阅读。题目简述给你一个均为小写字母的字符串,如果它的子串同时满足:三个连着的辅音字母。这一段连着的辅音字母不是全部一样的。就认为它不合法。现在要求用最少的空格隔开这个字符串,使得它变成......
  • AT_agc022_a 题解
    洛谷链接&Atcoder链接本篇题解为此题较简单做法及较少码量,并且码风优良,请放心阅读。题目简述给定字符串\(S\),仅包含互不相同的小写字母,你需要找到仅包含互不相同的小写字母的字符串中,第一个字典序比它大的字符串,如果找不到输出\(-1\)。(\(|S|\le26\))思路这篇题解......
  • 【题解】[2023牛客多校] Qu'est-ce Que C'est?
    题目传送门:[2023牛客多校]Qu'est-ceQueC'est?题意给定\(n,m\)构造\(a_{1},a_{2},...,a_{n}\),其中\(a_{i}\in[-m,m]\)之间取值。需要保证序列任意连续子段和都非负。\(0\leqn,m\leq5000\)分析记录合法序列的最小后缀。通过最小后缀来判断下一个数的取值范围。......
  • Codeforces Round 888 (Div. 3) 题解
    考场上\(7\)题做出来\(4\)题,最后几分钟才把D题调出来,但还是吃了不少罚时A.EscalatorConversations\(O(n)\)枚举即可,对于每个人计算需要的间隔台阶数是否在\((0,m)\)以内以及相差高度是否是\(k\)的倍数B.ParitySort显然,偶数和奇数是不可能产生交换操作的,而偶数......
  • P2679 [NOIP2015 提高组] 子串 题解
    原题\(题目大意\)\(从字符串a中选出k个子串s_1,s_2,s_3...s_k使得s_1+s_2+s_3+...+s_k=b\)\(求总方案数对10^9+7取模的结果\)\(1\le|a|即n\le1000,1\le|b|即m\le200,1\lek\le|b|\)\(设f_{i,j,x}表示已经选到a的第i个字符,b的第j个字符,共选了x个子串的方案数\)\(则可得......
  • 国标GB28181视频平台LntonGBS(源码版)国标视频平台大并发下SIP消息出现重复SN号的问题解
    随着国家倡导平安城市、智慧城市的建设,安防视频监控作为智慧城市安防建设的重要环节,也越来越受到重视。LntonGBS是基于公安部推出的安防主流协议(国标GB28181协议)的视频接入、处理及分发平台,具有视频直播监控、云端录像、云存储、检索回放、智能告警、语音对讲、平台级联等功能。我......
  • HDU1702 ACboy needs your help again! 题解
    #include<iostream>#include<string>#include<queue>#include<stack>usingnamespacestd;intt,n,m;intmain(){cin>>t;while(t--){queue<int>q;stack<int>s;stringop,str......
  • HDU4841 AHOI1999 圆桌问题 题解
    朴素的约瑟夫问题,用vector处理即可#include<iostream>#include<vector>usingnamespacestd;//AHOI1999圆桌问题类似于约瑟夫问题vector<int>table;intn,m;intmain(){while(cin>>n>>m){table.clear();for(inti=0;......
  • P2127 序列排序 题解
    原题题目意思\(有一个数列a,每次可以挑选任意两个元素交换位置,代价为这两个元素的和,问把序列a升序排序所需的最小总代价\)\(定义数列上的一个有i个元素的环S使得s_1要换到s_2,s_2要到s_3,……,s_i要到s_1\)\(原图一个元素只有一个目标位置,所以可以看作一个有n点,n边的有向图\)......