LuoguP2186 小Z的栈函数 题解
Update
- \(\texttt{2020.10.27}\) 修了一下排版。
Content
有一种程序给定你11种操作:
- \(\text{NUM }x\):在栈顶放入元素 \(x\)。
- \(\text{POP}\):栈顶元素出栈。
- \(\text{INV}\):栈顶元素出栈,取其相反数后再入栈。
- \(\text{DUP}\):在栈顶放入和栈顶元素一样的元素。
- \(\text{SWP}\):将栈顶的两个元素交换。
- \(\text{ADD}\):取出栈顶的两个元素,将两个元素的和入栈。
- \(\text{SUB}\):取出栈顶的两个元素,将第二个元素减去第一个元素的差入栈。
- \(\text{MUL}\):取出栈顶的两个元素,将两个元素的积入栈。
- \(\text{DIV}\):取出栈顶的两个元素,将第二个元素除以第一个元素(整除)之后的结果作为一个元素入栈。
- \(\text{MOD}\):取出栈顶的两个元素,将第二个元素取模以第一个元素之后的结果作为一个元素入栈。
- \(\text{END}\):结束程序。
现用 \(m\) 个操作(包含上面 \(11\) 种操作,但不全部包含,可能会有一种操作多次使用的情况)编写一个函数 \(f(x)\),其中 \(x\) 为最初栈里的唯一一个元素。\(f(x)\) 的结果即为 \(m\) 个操作完成以后栈里的唯一一个元素。
编写一个程序,接受 \(n\) 次询问,每次询问给出一个数 \(x_i\),让你根据对应的 \(x_i\) 求出 \(f(x_i)\)。注意,如果出现下列情况之一,输出 \(\texttt{ERROR}\):
- \(m\) 次操作结束后栈内没有元素或者有两个及以上的元素。
- 在 \(m\) 次操作中,有任意一个计算过程算出来的结果的绝对值 \(\geqslant 10^9\)。
- 输入数据不合法,导致中途退出。
数据范围:\(n,m\leqslant 2000\)。
Solution
大模拟题,考察的是栈的基本操作和字符串的基本操作,但细节很多(这应该是它蓝了的原因)。
先再逐一考虑每种操作的代码实现:
- \(\texttt{NUM}\) 操作:直接利用 \(\texttt{push}\) 函数即可。
- \(\texttt{POP}\) 操作:直接利用 \(\texttt{pop}\) 函数即可。
- \(\texttt{INV}\) 操作:将栈顶元素存储到一个变量中,然后进行 \(\texttt{pop}\) 操作,再将栈顶元素取相反数用 \(\texttt{push}\) 操作即可。
- \(\texttt{DUP}\) 操作:用一个变量存储栈顶元素但不将栈顶元素弹出栈,然后直接利用 \(\texttt{push}\) 函数即可。
- \(\texttt{SWP}\) 操作:连续两次 \(\texttt{pop}\) 操作,把先弹出来的元素先入栈,再将后弹出来的元素后入栈。不需要 \(\texttt{swap}\) 函数。
- \(\texttt{ADD}\) 操作:连续两次 \(\texttt{pop}\) 操作,然后将弹出来的两个元素求和后再将求得的结果入栈。
- \(\texttt{SUB}\) 操作:连续两次 \(\texttt{pop}\) 操作,然后将后弹出来的元素减去先弹出来的元素后再将所得到的差值入栈。
- \(\texttt{MUL}\) 操作:连续两次 \(\texttt{pop}\) 操作,然后将弹出来的两个元素求积后再将求得的结果入栈。
- \(\texttt{DIV}\) 操作:连续两次 \(\texttt{pop}\) 操作,然后将后弹出来的元素整除以先弹出来的元素后再将所得到的结果入栈。
- \(\texttt{MOD}\) 操作:连续两次 \(\texttt{pop}\) 操作,然后将后弹出来的元素取模以先弹出来的元素后再将所得到的结果入栈。
- \(\texttt{END}\) 操作:取出栈顶元素,如果里面仍不为空说明前面的操作做完了之后有两个及以上的元素,输出 \(\texttt{ERROR}\),否则输出这个栈顶元素。
另外还要提防:
- 每次操作中都可能会出现的运算结果的绝对值大于 \(10^9\) 的情况。
- \(\texttt{DIV}\) 和 \(\texttt{MOD}\) 操作中除数或模数为\(0\)的情况。
- 出现了除上述 \(11\) 种操作之外的操作的情况。
放心,整道题目代码量还不过 \(200\) 行,可以接受的。
总之,这道题目考察思维难度还算好,如果按思维难度评分的话,我认为最多给它评个橙题。
Code
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#include <stack>
#include <iostream>
using namespace std;
string move[2007];
int n, cnt;
long long x, move2[2007];
void mover(long long x) {
if(abs(x) > 1e9) {
puts("ERROR");
return;
}
stack<long long> q;
q.push(x);
for(int i = 1; i <= cnt; ++i) {
// cout << move[i] << endl;
if(move[i] == "NUM") {
if(abs(move2[i]) > 1e9) {
puts("ERROR");
return;
}
q.push(move2[i]);
} else if(move[i] == "POP") {
if(abs(q.top()) > 1e9 || q.empty()) {
puts("ERROR");
return;
}
q.pop();
} else if(move[i] == "INV") {
long long x = q.top();
if(abs(x) > 1e9 || q.empty()) {
puts("ERROR");
return;
}
q.pop();
q.push(-x);
} else if(move[i] == "DUP") {
long long x = q.top();
if(abs(x) > 1e9 || q.empty()) {
puts("ERROR");
return;
}
q.push(x);
} else if(move[i] == "SWP") {
long long x1 = q.top();
if(abs(x1) > 1e9 || q.empty()) {
puts("ERROR");
return;
}
q.pop();
long long x2 = q.top();
if(abs(x2) > 1e9 || q.empty()) {
puts("ERROR");
return;
}
q.pop();
q.push(x1);
q.push(x2);
} else if(move[i] == "ADD") {
long long x1 = q.top();
if(abs(x1) > 1e9 || q.empty()) {
puts("ERROR");
return;
}
q.pop();
long long x2 = q.top();
if(abs(x2) > 1e9 || q.empty()) {
puts("ERROR");
return;
}
q.pop();
long long x = x1 + x2;
if(abs(x) > 1e9) {
puts("ERROR");
return;
}
q.push(x);
} else if(move[i] == "SUB") {
long long x1 = q.top();
if(abs(x1) > 1e9 || q.empty()) {
puts("ERROR");
return;
}
q.pop();
long long x2 = q.top();
if(abs(x2) > 1e9 || q.empty()) {
puts("ERROR");
return;
}
q.pop();
long long x = x2 - x1;
if(abs(x) > 1e9) {
puts("ERROR");
return;
}
q.push(x);
} else if(move[i] == "MUL") {
long long x1 = q.top();
if(abs(x1) > 1e9 || q.empty()) {
puts("ERROR");
return;
}
q.pop();
long long x2 = q.top();
if(abs(x2) > 1e9 || q.empty()) {
puts("ERROR");
return;
}
q.pop();
long long x = x1 * x2;
if(abs(x) > 1e9) {
puts("ERROR");
return;
}
q.push(x);
} else if(move[i] == "DIV") {
long long x1 = q.top();
if(abs(x1) > 1e9 || q.empty() || !x1) {
puts("ERROR");
return;
}
q.pop();
long long x2 = q.top();
if(abs(x2) > 1e9 || q.empty()) {
puts("ERROR");
return;
}
q.pop();
long long x = x2 / x1;
if(abs(x) > 1e9) {
puts("ERROR");
return;
}
q.push(x);
} else if(move[i] == "MOD") {
long long x1 = q.top();
if(abs(x1) > 1e9 || q.empty() || !x1) {
puts("ERROR");
return;
}
q.pop();
long long x2 = q.top();
if(abs(x2) > 1e9 || q.empty()) {
puts("ERROR");
return;
}
q.pop();
long long x = x2 % x1;
if(abs(x) > 1e9) {
puts("ERROR");
return;
}
q.push(x);
} else if(move[i] == "END") {
long long x = q.top();
if(abs(x) > 1e9 || q.empty()) {
puts("ERROR");
return;
}
q.pop();
if(!q.empty()) {
puts("ERROR");
return;
}
printf("%lld\n", x);
} else {
puts("ERROR");
return;
}
}
}
int main() {
while(cin >> move[++cnt] && move[cnt] != "END") {
if(move[cnt] == "NUM")
scanf("%d", &move2[cnt]);
}
scanf("%d", &n);
while(n--) {
scanf("%lld", &x);
mover(x);
}
}