資訊學奧賽複賽複習09-CSP-J2020-03表示式求值前置知識點-中綴表示式求值、摸運算、模運算性質、棧

new-code發表於2024-10-02
PDF文件公眾號回覆關鍵字:20241002
資訊學奧賽複賽複習09-CSP-J2020-03表示式求值前置知識點-中綴表示式求值、摸運算、模運算性質、棧

**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;
} 

相關文章