日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

信息学奥赛一本通 1962:【13NOIP普及组】表达式求值 | 洛谷 P1981 [NOIP2013 普及组] 表达式求值

發(fā)布時間:2025/3/17 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 信息学奥赛一本通 1962:【13NOIP普及组】表达式求值 | 洛谷 P1981 [NOIP2013 普及组] 表达式求值 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

【題目鏈接】

ybt 1962:【13NOIP普及組】表達式求值
洛谷 P1981 [NOIP2013 普及組] 表達式求值

【題目考點】

  • 中綴表達式轉(zhuǎn)后綴表達式,后綴表達式求值
  • 中綴表達式求值
  • 【解題思路】

    表達式中只有加法和乘法,數(shù)字是0~231?10 \sim 2^{31}-10231?1,運算中不會出現(xiàn)負數(shù)。由于最后只需要最后4位,即結(jié)果%10000的值。根據(jù)同余定理:
    (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
    運算時,將每個數(shù)字都%10000,每次計算后的結(jié)果都%10000,最終得到的結(jié)果就是真實結(jié)果%10000后的值。
    具體解法有兩種

  • 先將中綴表達式轉(zhuǎn)為后綴表達式,而后求后綴表達式的值
  • 直接求中綴表達式的值
  • 【題解代碼】

    解法1:先將中綴表達式轉(zhuǎn)為后綴表達式,而后求后綴表達式的值

    中綴表達式轉(zhuǎn)后綴表達式方法:

  • 從左向右掃描表達式字符串。
  • 遇到數(shù)字時,直接輸出。
  • 遇到運算符時,如果棧空,或該運算符優(yōu)先級大于棧頂運算符優(yōu)先級,則入棧。否則運算符出棧并輸出。重復這一過程。
  • 掃描結(jié)束后若棧中有運算符,都出棧并輸出。
  • 后綴表達式求值:

  • 從左向右掃描字符串
  • 遇到數(shù)字時,將數(shù)字入棧。
  • 遇到運算符時,彈出棧頂?shù)膬蓚€數(shù),用該運算符對它們做相應的計算,結(jié)果入棧。
  • 掃描結(jié)束后,棧頂數(shù)字就是結(jié)果。
  • 本題解中,用一個數(shù)組e表示后綴表達式,數(shù)組中元素e[i]若大于等于0,表示數(shù)字。若e[i]為-1,表示乘號,若e[i]為-2,表示加號。這里乘號的值大于加號的值,可以表示乘號的優(yōu)先級大于加號。

    運算符最多10510^5105個,那么運算符與數(shù)字加起來不會超過3?1053*10^53?105個,所以數(shù)組大小開為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,表示數(shù)字。若e[i]為-1,表示乘號,若e[i]為-2,表示加號。e_i:e數(shù)組待添加元素的位置 int stk[2*N], top; int main() {char c;int num = 0, cVal, a, b;//cVal:運算符的值:加號為-2,乘號為-1; a,b:運算數(shù)c = getchar();//輸入并構(gòu)建后綴表達式while(c != EOF && c != '\n')//不確定OJ輸入的末尾是文件末尾EOF,還是換行符'\n',所以二者都可能是輸入的結(jié)束符號,都判斷一下。{if(c >= '0' && c <= '9')//c是數(shù)字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比棧頂運算符的優(yōu)先級相等或更低,則運算符出棧,輸出到后綴表達式e[e_i++] = stk[top--];stk[++top] = cVal;//此時運算符入棧}c = getchar();}e[e_i++] = num;//添加最后一個數(shù)字while(top > 0)//將棧中剩余的運算符加入后綴表達式e[e_i++] = stk[top--];//此時后綴表達式構(gòu)建完成,開始根據(jù)后綴表達式求值for(int i = 0; i < e_i; ++i){if(e[i] >= 0)//如果是數(shù)字stk[++top] = e[i];//數(shù)字入棧else//如果是運算符{a = stk[top--];//數(shù)字出棧b = stk[top--];//數(shù)字出棧if(e[i] == ADD)//如果是加號stk[++top] = (a + b) % M;//計算結(jié)果入棧else//如果是乘號stk[++top] = (a * b) % M;//計算結(jié)果入棧}}cout<<stk[top];//棧頂數(shù)值即為運算結(jié)果return 0; }

    解法2:直接求中綴表達式的值

    中綴表達式求值:

  • 設數(shù)字棧,運算符棧。從左向右掃描表達式
  • 遇到數(shù)字進數(shù)字棧
  • 遇到運算符,如果運算符棧棧空,或該運算符優(yōu)先級大于棧頂運算符優(yōu)先級,則入棧。否則運算符出棧,從數(shù)字棧出棧2個數(shù)字,進行計算,結(jié)果在數(shù)字棧入棧。重復這一過程。
  • 掃描結(jié)束后,運算符棧出棧運算符,進行運算,直到運算符棧為空。最后數(shù)字棧棧頂?shù)臄?shù)字,就是結(jié)果。
  • #include<bits/stdc++.h> using namespace std; #define N 100005 #define M 10000 int nStk[N], nTop, cTop;//nStk:數(shù)字棧 nTop:數(shù)字棧棧頂位置 cTop:運算符棧棧頂位置 char cStk[N];//cStk:運算符棧 int main() {char c, tc;//c:讀入的字符 tc:出棧的字符int num = 0, a, b;c = getchar();while(c != EOF && c != '\n'){if(c >= '0' && c <= '9')//如果遇到數(shù)字字符num = (num * 10 + c - '0') % M;else//如果遇到運算符{nStk[++nTop] = num;num = 0;while(!(cTop == 0 || c == '*' && cStk[cTop] == '+'))//棧空或要入棧的運算符比棧頂運算符優(yōu)先級高,才可以入棧,其他情況都出棧,做運算。{a = nStk[nTop--];//數(shù)字棧出棧兩個數(shù)b = nStk[nTop--];tc = cStk[cTop--];//運算符棧出棧一個運算符,if(tc == '*')//進行計算,結(jié)果存入數(shù)字棧nStk[++nTop] = (a * b) % M;elsenStk[++nTop] = (a + b) % M;}cStk[++cTop] = c;}c = getchar();}nStk[++nTop] = num;//添加最后一個數(shù)字while(cTop > 0)//如果運算符棧還有運算符,運算符出棧,運算,直到棧空為止{a = nStk[nTop--];//數(shù)字棧出棧兩個數(shù)b = nStk[nTop--];tc = cStk[cTop--];//運算符棧出棧一個運算符,if(tc == '*')//進行計算,結(jié)果存入數(shù)字棧nStk[++nTop] = (a * b) % M;elsenStk[++nTop] = (a + b) % M;}cout<<nStk[nTop];//數(shù)字棧棧頂即為結(jié)果return 0; }

    同樣解法,使用string讀入,使用c++ stl的stack類來做

    #include<bits/stdc++.h> using namespace std; #define N 100005 #define M 10000 stack<int> nStk;//nStk:數(shù)字棧 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);//最后的數(shù)字入棧 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; } 新人創(chuàng)作打卡挑戰(zhàn)賽發(fā)博客就能抽獎!定制產(chǎn)品紅包拿不停!

    總結(jié)

    以上是生活随笔為你收集整理的信息学奥赛一本通 1962:【13NOIP普及组】表达式求值 | 洛谷 P1981 [NOIP2013 普及组] 表达式求值的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。