信息学奥赛一本通 1962:【13NOIP普及组】表达式求值 | 洛谷 P1981 [NOIP2013 普及组] 表达式求值
【題目鏈接】
ybt 1962:【13NOIP普及組】表達式求值
洛谷 P1981 [NOIP2013 普及組] 表達式求值
【題目考點】
【解題思路】
表達式中只有加法和乘法,數字是0~231?10 \sim 2^{31}-10~231?1,運算中不會出現負數。由于最后只需要最后4位,即結果%10000的值。根據同余定理:
(a+b)%m=(a%m+b%m)%m(a+b)\%m = (a\%m+b\%m)\%m(a+b)%m=(a%m+b%m)%m,(a?b)%m=((a%m)?(b%m))%m(a*b)\%m = ((a\%m)*(b\%m))\%m(a?b)%m=((a%m)?(b%m))%m。
運算時,將每個數字都%10000,每次計算后的結果都%10000,最終得到的結果就是真實結果%10000后的值。
具體解法有兩種
【題解代碼】
解法1:先將中綴表達式轉為后綴表達式,而后求后綴表達式的值
中綴表達式轉后綴表達式方法:
后綴表達式求值:
本題解中,用一個數組e表示后綴表達式,數組中元素e[i]若大于等于0,表示數字。若e[i]為-1,表示乘號,若e[i]為-2,表示加號。這里乘號的值大于加號的值,可以表示乘號的優先級大于加號。
運算符最多10510^5105個,那么運算符與數字加起來不會超過3?1053*10^53?105個,所以數組大小開為3?1053*10^53?105。
#include <bits/stdc++.h> using namespace std; #define N 100000 #define M 10000 #define ADD -2 //加號 #define MULT -1//乘號 int e[3*N], e_i;//保存后綴表達式,e[i]若大于等于0,表示數字。若e[i]為-1,表示乘號,若e[i]為-2,表示加號。e_i:e數組待添加元素的位置 int stk[2*N], top; int main() {char c;int num = 0, cVal, a, b;//cVal:運算符的值:加號為-2,乘號為-1; a,b:運算數c = getchar();//輸入并構建后綴表達式while(c != EOF && c != '\n')//不確定OJ輸入的末尾是文件末尾EOF,還是換行符'\n',所以二者都可能是輸入的結束符號,都判斷一下。{if(c >= '0' && c <= '9')//c是數字num = (num * 10 + c - '0') % M;else//c是運算符{e[e_i++] = num;//后綴表達式添加numnum = 0;if(c == '+')cVal = ADD;//如果是加號elsecVal = MULT;//如果是乘號while(!(top == 0 || cVal > stk[top]))//如果棧中有運算符,且運算符c比棧頂運算符的優先級相等或更低,則運算符出棧,輸出到后綴表達式e[e_i++] = stk[top--];stk[++top] = cVal;//此時運算符入棧}c = getchar();}e[e_i++] = num;//添加最后一個數字while(top > 0)//將棧中剩余的運算符加入后綴表達式e[e_i++] = stk[top--];//此時后綴表達式構建完成,開始根據后綴表達式求值for(int i = 0; i < e_i; ++i){if(e[i] >= 0)//如果是數字stk[++top] = e[i];//數字入棧else//如果是運算符{a = stk[top--];//數字出棧b = stk[top--];//數字出棧if(e[i] == ADD)//如果是加號stk[++top] = (a + b) % M;//計算結果入棧else//如果是乘號stk[++top] = (a * b) % M;//計算結果入棧}}cout<<stk[top];//棧頂數值即為運算結果return 0; }解法2:直接求中綴表達式的值
中綴表達式求值:
同樣解法,使用string讀入,使用c++ stl的stack類來做
#include<bits/stdc++.h> using namespace std; #define N 100005 #define M 10000 stack<int> nStk;//nStk:數字棧 stack<char> cStk;//cStk:運算符棧 string s; int main() {char c;int num = 0, a, b;cin>>s;for(int i = 0; i < s.length(); ++i){if(s[i] >= '0' && s[i] <= '9')num = (num * 10 + s[i] - '0') % M;else{nStk.push(num);num = 0;while(!(cStk.empty() || s[i] == '*' && cStk.top() == '+')){b = nStk.top(); nStk.pop();a = nStk.top(); nStk.pop();c = cStk.top(); cStk.pop();if(c == '*')nStk.push(a * b % M);elsenStk.push((a + b) % M);}cStk.push(s[i]);}}nStk.push(num);//最后的數字入棧 while(cStk.empty() == false)//其余運算符出棧,運算 {b = nStk.top(); nStk.pop();a = nStk.top(); nStk.pop();c = cStk.top(); cStk.pop();if(c == '*')nStk.push(a * b % M);elsenStk.push((a + b) % M);}cout<<nStk.top();fclose(stdin);return 0; } 新人創作打卡挑戰賽發博客就能抽獎!定制產品紅包拿不停!總結
以上是生活随笔為你收集整理的信息学奥赛一本通 1962:【13NOIP普及组】表达式求值 | 洛谷 P1981 [NOIP2013 普及组] 表达式求值的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 信息学奥赛一本通(2033:【例4.19
- 下一篇: 信息学奥赛一本通 2021:【例4.6】