PDF文件公眾號回覆關鍵字:20241002
**1 P1981 [NOIP2013普及組] 表示式求值 **
[題目描述]
給定一個只包含加法和乘法的算術表示式,請你程式設計計算表示式的值
[輸入格式]
一行,為需要你計算的表示式,表示式中只包含數字、加法運算子 “+” 和乘法運算子 “×”,且沒有括號,所有參與運算的數字均為 0 到 2^31之間的整數。
輸入資料保證這一行只有 0∼9、+、× 這 12種字元
[輸出格式]
一個整數,表示這個表示式的值。
注意:當答案長度多於 4 位時,請只輸出最後 4 位,前導 0 不輸出
[輸入輸出樣例]
輸入 #1
1+1*3+4
輸出 #1
8
輸入 #2
1+1234567890*1
輸出 #2
7891
輸入 #3
1+1000000003*1
輸出 #2
4
說明/提示
對於 30% 的資料,0≤ 表示式中加法運算子和乘法運算子的總數 ≤100。
對於 80% 的資料,0≤ 表示式中加法運算子和乘法運算子的總數 ≤1000。
對於 100% 的資料,0≤ 表示式中加法運算子和乘法運算子的總數 ≤100000。
2 相關知識點
1) 模運算
模運算,就是取餘數,在計算機語言中用%來表示。舉個簡單的例子,3 % 5 = 3。結果的取值範圍在 0 與模之間
例如
c=x/y
c=3 mod 5 =3 c的取值範圍 [0,y-1]
結果也可以用負數表示,即 c=-2
2) 模運算性質
(a + b) % p = (a % p + b % p) % p
(a - b) % p = (a % p - b % p ) % p
(a * b) % p = (a % p * b % p) % p
a ^ b % p = ((a % p)^b) % p
3) 棧
棧又名堆疊,是一種限定僅在表尾進行插入和刪除操作的線性表,這一端稱為棧頂,另一端稱為棧底
棧中的資料元素遵守後進先出的原則
4) 中綴表示式
是一種常見的算術表示式表示方法,其中運算子位於運算元之間
例如
//示例1
3 + 4 * 2
//示例2
(1 + 2) * (3 - 4)
3 思路分析
由於本題只有2個運算元,+和*,且*的優先順序大於+
因此可以提前先把*計算出來,剩餘都是+運算子,再統一計算加
例如如下表示式,具體步驟如下
1+1*3+4
每次輸入一個運算子和一個運算元
遇到*號,從棧中取出棧頂運算元和本次讀取的運算元相乘
相乘的結果存入棧中
2讀入下一個運算子+和運算元4
直接把4放入棧中
3 棧中3個運算元只剩下1種運算子+
遍歷棧對這3個運算元相加,即為表示式的值
示例程式
#include<bits/stdc++.h>
using namespace std;
/*
棧
1 儲存 *前的運算元和相乘後的結果
2 儲存 + 號前後的運算元
*/
stack<int> st;
int f,t,ans;//f第1個運算元 t第2個運算元 ans運算結果
char s;//運算子
const int m=10000;//只輸出最後4位,結果對m取模
int main(){
cin>>f;//輸入第1個運算元
st.push(f%10000);//根據模運算乘法和加法性質,可以先取模
while(cin>>s>>t){//輸入運算子號和第2個運算元,直到結束
if(s=='*'){//乘法提前計算結果,再存入棧,保證棧中只保留加法運算
f=st.top();//從棧中取出第1個運算元
st.pop();//彈出上面取出的運算元
/*
把結算結果存入棧,後續把結果相加
根據模運算加法性質,可以先取模
*/
st.push(f*t%m);
}else{//加法運算子 直接存入棧,後續取出相加
st.push(t);
}
}
//遍歷棧,棧中保留的都是加法運算元,可以直接相加
while(st.size()!=0){//遍歷棧,直到沒有任何元素
ans=(ans+st.top())%m;//把棧中每個數累加到ans
st.pop();//累加後 從棧中彈出
}
cout<<ans;//輸出運算結果
return 0;
}