1. 程式人生 > 遊戲 >時隔六年再度迴歸?索尼一年內三次更新PS Home商標

時隔六年再度迴歸?索尼一年內三次更新PS Home商標

表示式求值常常是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\)

,其中\(|S|\)為字串\(S\)的長度。

保證表示式僅包含數字、左右括號、加號、減號、乘號,且表示式中的數字均為整數且\(\in [0,2527)\)

一、棧思想

我因為過於辣雞,只好用了一個棧存數與符號。
可是一個棧怎麼同時存數與符號呢?機智的我把2528認作+,把2529認作-,把2529認作*,把2529認作(。至於為什麼沒有),後面再說。
可惡的資料竟然出現了超過2527的數,於是我後面程式碼裡都在前面加了一個2(在此感謝hjy同學的猜測)。

每次對於一個字元,我們分類討論:

  1. 如果他是數字,加在前面的數字裡,繼續往後;
  2. 如果是加減乘和右括號,說明數已經輸入完畢,進入情況1,然後把數推入棧。(左括號前面肯定有符號)
  3. 如果是加減乘和左括號,就把他們推入棧中。
  4. 右括號進入情況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);
}

-完結撒花-