题解 P1054 【等价表达式】

· · 题解

一道考察中缀求值+乱搞的好题。

如果按多项式处理,显然不行。

取几个常量代入即可,可以通过某种神奇的方法得到

如果这几个常量对应的值都相等,等价的概率极高(估计有%99.99999)

#include<cstdio>
#include<cstring>
#define INF 7000007
#define x1 17
#define x2 29
int i,p,n,m,topnum=0,topsym=0;
long long ansa,ansb;
char a[51],sym[51];
struct expression
{
    long long y1,y2;
} num[51];
short level(char ch) //优先级 
{
    switch (ch)
    {
        case '+': return 1; break;
        case '-': return 1; break;
        case '*': return 2; break;
        case '^': return 3; break;
        case '(': return 0; break;
    } 
}
void calc(char ch)
{
    long long a1=num[topnum-1].y1,b1=num[topnum].y1;
    long long a2=num[topnum-1].y2,b2=num[topnum].y2;
    if (ch=='+')
    {
        num[topnum-1].y1=(a1+b1)%INF;
        num[--topnum].y2=(a2+b2)%INF;
    }
    else if (ch=='-')
    {
        num[topnum-1].y1=(a1-b1)%INF;
        if (num[topnum-1].y1<0) num[topnum-1].y1+=INF;
        num[--topnum].y2=(a2-b2)%INF;
        if (num[topnum].y2<0) num[topnum].y2+=INF;
    }
    else if (ch=='*')
    {
        num[topnum-1].y1=(a1%INF*b1)%INF;
        num[--topnum].y2=(a2%INF*b2)%INF;
    }
    else if (ch=='^')
    {
        long long cnt=a1;
        for (int i=1; i<b1; i++) //直接O(n) 
          cnt=(cnt*a1)%INF;
        num[topnum-1].y1=cnt;
        cnt=a2;
        for (int i=1; i<b2; i++)
          cnt=(cnt*a2)%INF;
        num[--topnum].y2=cnt;
    }
}
void work()
{
    gets(a);
    m=strlen(a);
    p=0;
    while (p<m)
    {
        if (a[p]==' ') { p++; continue; } //自动过滤(用gets的话一定要写)
        if (a[p]>='0'&&a[p]<='9') //数字 
        {
            int x=a[p++]-'0';
            while (a[p]>='0'&&a[p]<='9')
              x=10*x+a[p++]-'0';
            p--;
            num[++topnum].y1=x; num[topnum].y2=x;
        }
        else if (a[p]=='a') //a用某个常量代替,以免进行多项式乘法 
        {
            num[++topnum].y1=x1; num[topnum].y2=x2;            
        }
        else if (a[p]=='(') sym[++topsym]='(';
        else if (a[p]==')') 
        {
            while (topsym>1 && sym[topsym]!='(')
              calc(sym[topsym--]);
            if (topsym>=1) topsym--;
        }
        else if (topsym==0 || level(sym[topsym])<level(a[p])) 
            sym[++topsym]=a[p];
        else //运算符运算 
        {
            calc(sym[topsym--]);
            while (topsym>0 && level(sym[topsym])>=level(a[p]))
              calc(sym[topsym--]);
            sym[++topsym]=a[p];
        }
        p++;
    }
    while (topsym>0)
      calc(sym[topsym--]);        
}
int main()
{  
    work();
    ansa=num[1].y1;
    ansb=num[1].y2;
    topnum=0;
    scanf("%d",&n);
    gets(a);
    for (i=0; i<n; i++)
    {        
        work();
        if (num[1].y1==ansa && num[1].y2==ansb)
          printf("%c",'A'+i);
        topnum=0;
    }
    return 0;
}