本文最后更新于 1126 天前,其中的信息可能已经有所发展或是发生改变。
题解
这个题是一道恶心人的大模拟,如何处理检查配平情况呢?要找出所有的原子,计数,然后比对等号两边各种原子的数量。
处理原子可以用 unordered_map
,但是效率不高切更难写,我们可以开一个 $27*27$ 的数组,把原子转换为数组下标,这样更高效。
关于括号的嵌套,我的想法是开一个 tag
数组,先扫一个化学式,确定括号的位置以及化学计量数,然后更新 tag
,正数代表乘,负数代表除。
还有一个容易出现的 bug:数字有可能出现很多位,刚开始我只考虑了一位,所以调了很久。
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 27 * 27 + 5;
#define SIZ s.size()
int a[N], b[N];
int tag[1005];
int n;
int ans;
string s;
void div1(string str) {
// cout << str << endl;
for (int i = 0; i < str.size();) {
int j = i + 1;
while (str[j] != '+' && j < str.size())
j++;
string cur = str.substr(i, j - i);
i = j + 1;
int times = 1;
int now = 0;
memset(tag, 0, sizeof tag);
if (cur[0] >= '1' && cur[0] <= '9') {
int number = 0;
while (cur[now] >= '0' && cur[now] <= '9') {
number = number * 10 + cur[now] - '0';
now++;
}
times *= number;
now--;
}
while (now < cur.size()) {
if (cur[now] == '(') {
int l = 1, k = now + 1;
while (1) {
if (cur[k] == '(')
l++;
if (cur[k] == ')')
l--;
if (l == 0) {
int tmp = 0;
if (cur[k + 1] < '0' || cur[k + 1] > '9')
tmp = 1;
int p = k + 1;
while (cur[p] >= '0' && cur[p] <= '9') {
tmp = tmp * 10 + cur[p] - '0';
p++;
}
tag[now] = tmp;
tag[k] = tmp * -1;
cerr << "add tag on " << now << " value = " << tmp
<< endl;
break;
}
k++;
}
}
now++;
}
now = 0;
while (1) {
if (now >= cur.size())
break;
if (tag[now] > 0)
times *= tag[now];
if (tag[now] < 0)
times /= tag[now] * -1;
if (!((cur[now] >= 'a' && cur[now] <= 'z') ||
(cur[now] >= 'A' && cur[now] <= 'Z'))) {
now++;
continue;
}
int tim = 1;
if ((cur[now + 1] >= 'A' && cur[now + 1] <= 'Z') ||
cur[now + 1] == '(' || cur[now + 1] == ')' ||
now + 1 >= cur.size()) {
a[(cur[now] - 'A' + 1) * 10] += 1 * times;
cerr << "find " << cur[now] << " 我们给他加上了 " << 1 * times
<< endl;
}
if ((cur[now + 1] >= '0' && cur[now + 1] <= '9')) {
int number = 0;
int p = now + 1;
while (cur[p] >= '0' && cur[p] <= '9') {
number = number * 10 + cur[p] - '0';
p++;
}
a[(cur[now] - 'A' + 1) * 10] += (number)*times;
cerr << "find " << cur[now] << number << " 我们给他加上了 "
<< (number)*times << endl;
now = p - 1;
}
if ((cur[now + 1] >= 'a' && cur[now + 1] <= 'z')) {
if ((cur[now + 2] >= '0' && cur[now + 2] <= '9')) {
int number = 0;
int p = now + 2;
while (cur[p] >= '0' && cur[p] <= '9') {
number = number * 10 + cur[p] - '0';
p++;
}
cerr << "find Aa0" << cur[now] << cur[now + 1]
<< cur[now + 2] << " 我们给他加上了 " << (number)*times
<< endl;
a[(cur[now] - 'A' + 1) * 10 + cur[now + 1] - 'a' + 1] +=
(number)*times;
now = p - 1;
} else {
cerr << "find Aa" << cur[now] << cur[now + 1]
<< " 我们给他加上了 " << 1 * times << endl;
a[(cur[now] - 'A' + 1) * 10 + cur[now + 1] - 'a' + 1] +=
(1) * times,
now++;
}
}
now++;
}
// for (int i = 0; i <= 20; i++)
// cout << tag[i] << " ";
// cout << endl;
// int qaq = 0;
}
}
void div2(string str) {
// cout << str << endl;
for (int i = 0; i < str.size();) {
int j = i + 1;
while (str[j] != '+' && j < str.size())
j++;
string cur = str.substr(i, j - i);
i = j + 1;
int times = 1;
int now = 0;
memset(tag, 0, sizeof tag);
if (cur[0] >= '1' && cur[0] <= '9') {
int number = 0;
while (cur[now] >= '0' && cur[now] <= '9') {
number = number * 10 + cur[now] - '0';
now++;
}
times *= number;
now--;
}
while (now < cur.size()) {
if (cur[now] == '(') {
int l = 1, k = now + 1;
while (1) {
if (cur[k] == '(')
l++;
if (cur[k] == ')')
l--;
if (l == 0) {
int tmp = 0;
if (cur[k + 1] < '0' || cur[k + 1] > '9')
tmp = 1;
int p = k + 1;
while (cur[p] >= '0' && cur[p] <= '9') {
tmp = tmp * 10 + cur[p] - '0';
p++;
}
tag[now] = tmp;
tag[k] = tmp * -1;
cerr << "add tag on " << now << " value = " << tmp
<< endl;
break;
}
k++;
}
}
now++;
}
now = 0;
while (1) {
if (now >= cur.size())
break;
if (tag[now] > 0)
times *= tag[now];
if (tag[now] < 0)
times /= tag[now] * -1;
if (!((cur[now] >= 'a' && cur[now] <= 'z') ||
(cur[now] >= 'A' && cur[now] <= 'Z'))) {
now++;
continue;
}
int tim = 1;
if ((cur[now + 1] >= 'A' && cur[now + 1] <= 'Z') ||
cur[now + 1] == '(' || cur[now + 1] == ')' ||
now + 1 >= cur.size()) {
b[(cur[now] - 'A' + 1) * 10] += 1 * times;
cerr << "find " << cur[now] << " 我们给他加上了 " << 1 * times
<< endl;
}
if ((cur[now + 1] >= '0' && cur[now + 1] <= '9')) {
int number = 0;
int p = now + 1;
while (cur[p] >= '0' && cur[p] <= '9') {
number = number * 10 + cur[p] - '0';
p++;
}
b[(cur[now] - 'A' + 1) * 10] += (number)*times;
cerr << "find " << cur[now] << number << " 我们给他加上了 "
<< (number)*times << endl;
now = p - 1;
}
if ((cur[now + 1] >= 'a' && cur[now + 1] <= 'z')) {
if ((cur[now + 2] >= '0' && cur[now + 2] <= '9')) {
int number = 0;
int p = now + 2;
while (cur[p] >= '0' && cur[p] <= '9') {
number = number * 10 + cur[p] - '0';
p++;
}
cerr << "find Aa0" << cur[now] << cur[now + 1]
<< cur[now + 2] << " 我们给他加上了 " << (number)*times
<< endl;
b[(cur[now] - 'A' + 1) * 10 + cur[now + 1] - 'a' + 1] +=
(number)*times;
now = p - 1;
} else {
cerr << "find Aa" << cur[now] << cur[now + 1]
<< " 我们给他加上了 " << 1 * times << endl;
b[(cur[now] - 'A' + 1) * 10 + cur[now + 1] - 'a' + 1] +=
(1) * times,
now++;
}
}
now++;
}
// for (int i = 0; i <= 20; i++)
// cout << tag[i] << " ";
// cout << endl;
// int qaq = 0;
}
}
void pd() {
for (int i = 0; i < N; i++)
if (a[i] != b[i]) {
cout << "N" << endl;
return;
}
cout << "Y" << endl;
return;
}
int main() {
scanf("%d", &n);
while (n--) {
cin >> s;
memset(a, 0, sizeof a);
memset(b, 0, sizeof b);
ans = 0;
for (int i = 0; i < SIZ; i++) {
if (s[i] != '=')
continue;
div1(s.substr(0, i));
div2(s.substr(i + 1));
}
pd();
}
}