時隔六年再度迴歸?索尼一年內三次更新PS Home商標
阿新 • • 發佈:2021-07-26
表示式求值常常是cxy的一大煩惱。總是會出各種錯誤,究竟該怎麼辦?今天,我來講解一下我寫的魔鬼版本——棧。
〇、題面
問題描述
給定一個只包含加(+
)、減(-
)、乘(*
)三種運算的\(n\)個字元的合法表示式,請求出該表示式的值對\(2527\)取餘後的結果。
輸入格式
第一行輸入一個字串\(S\),表示一個合法表示式。
輸出格式
輸出一個整數,表示該表示式的值對\(2527\)取餘後的結果。
樣例輸入1
(26*3*8)+(1*11)-(9*15*9)
樣例輸出1
1947
樣例輸入2
(510*510+208)-(511*511-813)
樣例輸出2
0
評測用例規模與約定
\(1\leq |S|\leq 5\times 10^6\)
保證表示式僅包含數字、左右括號、加號、減號、乘號,且表示式中的數字均為整數且\(\in [0,2527)\)。
一、棧思想
我因為過於辣雞,只好用了一個棧存數與符號。
可是一個棧怎麼同時存數與符號呢?機智的我把2528認作+
,把2529認作-
,把2529認作*
,把2529認作(
。至於為什麼沒有)
,後面再說。
可惡的資料竟然出現了超過2527的數,於是我後面程式碼裡都在前面加了一個2(在此感謝hjy同學的猜測)。
每次對於一個字元,我們分類討論:
- 如果他是數字,加在前面的數字裡,繼續往後;
- 如果是加減乘和右括號,說明數已經輸入完畢,進入情況1,然後把數推入棧。(左括號前面肯定有符號)
- 如果是加減乘和左括號,就把他們推入棧中。
- 右括號進入情況2。
情況1:
因為數讀入完了,所以我們需要處理一下。如果棧頂此時是乘號,那彈出棧頂,把新棧頂變為新棧頂乘輸入完的數。這樣,右括號處理時就只需要加減法了。
不是乘號,直接放入棧中。
之後(程式碼裡可以搞清楚),清空儲存數的東西。
情況2:
現在這個括號結束了,經過上面的整合只剩下一堆加減,方便極了。這裡貼程式碼:
if(c==')'){ n2=0;//n2表示當前數 while(st.top()!=22531){//22531是左括號 n2=st.top();//首先獲取當前數 st.pop();//彈掉這個數 if(st.top()==22529) now-=n2;//減法,即...-XXX... else now+=n2;//加法...+XXX... now%=2527;//取餘 if(st.top()!=22531) st.pop();//只要沒有到結束(要留著)就去掉符號 } st.pop();//去掉左括號 if(!st.empty()&&st.top()==22530){//非空且是乘號 st.pop();//彈出乘號 now*=st.top();//乘上 now%=2527;//取餘 st.pop();//彈出這個數 } st.push(now);//再把一通計算的結果放進去 now=0;//恢復出廠設定 continue;//跳過後面 }
二、程式碼(無註釋)
#include<iostream>
#include<cstdio>
#include<stack>
using namespace std;
stack<int> st;//22528=+,22529=-,22530=*,22531=(
int main(){
ios::sync_with_stdio(0);
string s;
char c;
cin>>s;
int l=s.size(),now=0,n2;
bool get=0;
st.push(22531);
s+=')';
for(int i=0;i<=l;i++){
c=s[i];
if(c=='+'||c=='-'||c=='*'||c==')'){
if(st.top()==22530){
st.pop();
now*=st.top();
now%=2527;
st.pop();
}
if(get) st.push(now);
now=0;
get=0;
}
if(c=='+') st.push(22528);
if(c=='-') st.push(22529);
if(c=='*') st.push(22530);
if(c=='(') st.push(22531);
if(c==')'){
n2=0;
while(st.top()!=22531){
n2=st.top();
st.pop();
if(st.top()==22529) now-=n2;
else now+=n2;
now%=2527;
if(st.top()!=22531) st.pop();
}
st.pop();
if(!st.empty()&&st.top()==22530){
st.pop();
now*=st.top();
now%=2527;
st.pop();
}
st.push(now);
now=0;
continue;
}
if(c>='0'&&c<='9'){
now=now*10+(c-'0');
get=1;
}
}
cout<<((st.top()%2527)+2527)%2527<<endl;
int _=0;
return ~~(0^_^0);
}
-完結撒花-