1. 程式人生 > >P1054 等價表達式

P1054 等價表達式

mes 一個 nbsp 它的 size space 包括 con const

題目描述

明明進了中學之後,學到了代數表達式。有一天,他碰到一個很麻煩的選擇題。這個題目的題幹中首先給出了一個代數表達式,然後列出了若幹選項,每個選項也是一個代數表達式,題目的要求是判斷選項中哪些代數表達式是和題幹中的表達式等價的。

這個題目手算很麻煩,因為明明對計算機編程很感興趣,所以他想是不是可以用計算機來解決這個問題。假設你是明明,能完成這個任務嗎?

這個選擇題中的每個表達式都滿足下面的性質:

  1. 表達式只可能包含一個變量‘aa’。
  2. 表達式中出現的數都是正整數,而且都小於1000010000。
  3. 表達式中可以包括四種運算+(加),-(減),*(乘),^(乘冪),以及小括號(
    ,)。小括號的優先級最高,其次是^,然後是*,最後是+-+-的優先級是相同的。相同優先級的運算從左到右進行。(註意:運算符+-*^以及小括號()都是英文字符)
  4. 冪指數只可能是11到1010之間的正整數(包括11和1010)。
  5. 表達式內部,頭部或者尾部都可能有一些多余的空格。

下面是一些合理的表達式的例子:

((a^1) ^ 2)^3a*a+a-a((a+a))9999+(a-a)*a1 + (a -1)^31^10^9………

輸入輸出格式

輸入格式:

第一行給出的是題幹中的表達式。

第二行是一個整數n(2 \le n \le 26)n(2n26),表示選項的個數。後面nn行,每行包括一個選項中的表達式。這nn個選項的標號分別是A,B,C,D…A,B,C,D

輸入中的表達式的長度都不超過50個字符,而且保證選項中總有表達式和題幹中的表達式是等價的。

輸出格式:

一行,包括一系列選項的標號,表示哪些選項是和題幹中的表達式等價的。選項的標號按照字母順序排列,而且之間沒有空格。

輸入輸出樣例

輸入樣例#1:
( a + 1) ^2
3
(a-1)^2+4*a
a + 1+ a
a^2 + 2 * a * 1 + 1^2 + 10 -10 +a -a
輸出樣例#1:
AC

說明

對於30%的數據,表達式中只可能出現兩種運算符‘+’和-
對於其它的數據,四種運算符+-

*^在表達式中都可能出現。
對於全部的數據,表達式中都可能出現小括號()

2005年提高組第四題

Solution:

  Noip的題目,滿滿的惡意((?◇?)?讀入有毒啊!)。

  讀入一行字符串,本題不能用gets或者cin.getline(因為我試了),所以得手寫讀入(判斷換行‘\n‘和回車‘\r‘)。

  思路就是隨便代10個數計算每個表達式的值,然後判斷是否都相等就好了。

  求的話可以用雙棧模擬(一個存數,一個單調維護符號優先級),或者遞歸求,遞歸過程直接區間從後往前,用hash的思路統計算術優先級(優先級:‘(‘>‘^‘>‘*‘>‘+‘=‘-‘>‘)‘),優先運算優先級高的就好了。

代碼:

/*Code by 520 -- 8.31*/
#include<bits/stdc++.h>
#define il inline
#define ll long long
#define RE register
#define For(i,a,b) for(RE int (i)=(a);(i)<=(b);(i)++)
#define Bor(i,a,b) for(RE int (i)=(b);(i)>=(a);(i)--)
using namespace std;
const int N=55,mod=1e9+7;
int n,len[N],sum[N];
char s[27][N],t[N];

il ll fast(ll x,ll k){
    ll ans=1;
    while(k){
        if(k&1) ans=ans*x%mod;
        k>>=1;
        x=x*x%mod;
    }
    return ans;
}

int p[N];
ll dfs(char *s,int l,int r,int x){
    int tot=0,minn=0x7fffffff,pos=l,cnt=0,num=0;
    memset(p,0x3f,sizeof(p));
    Bor(i,l,r){
        if(s[i]==)) tot+=100;
        if(s[i]==() tot-=100;
        if(s[i]==^) p[i]=tot+3,cnt++;
        if(s[i]==*) p[i]=tot+2,cnt++;
        if(s[i]==+||s[i]==-) p[i]=tot+1,cnt++;
        if(minn>p[i]) minn=p[i],pos=i;
    }
    if(!cnt){
        For(i,l,r) if(s[i]==a)return x;
        For(i,l,r) if(isdigit(s[i])) num=(num<<3)+(num<<1)+(s[i]^48);
        return num;
    }
    if(s[pos]==^) return fast(dfs(s,l,pos-1,x),dfs(s,pos+1,r,x));
    if(s[pos]==*) return dfs(s,l,pos-1,x)*dfs(s,pos+1,r,x)%mod;
    if(s[pos]==+) return (dfs(s,l,pos-1,x)+dfs(s,pos+1,r,x))%mod;
    if(s[pos]==-) return (dfs(s,l,pos-1,x)-dfs(s,pos+1,r,x))%mod;
    return 0;
}

il void get(char *a){
    char c=getchar();
    int cnt=0;
    while(c==\n||c==\r) c=getchar();
    while(c!=\n&&c!=\r) a[cnt++]=c,c=getchar();
    a[cnt]=\0;
}

int main(){
    get(t),len[0]=strlen(t);
    cin>>n;
    For(i,1,n) get(s[i]),len[i]=strlen(s[i]);
    For(i,0,10) sum[i]=dfs(t,0,len[0]-1,i-5);
    For(i,1,n) {
        bool f=0;
        For(j,0,10) if(sum[j]!=dfs(s[i],0,len[i]-1,j-5)){f=1;break;}
        if(!f)printf("%c",A+i-1);
    }
    return 0;
}

P1054 等價表達式