Luogu P1054 Problem Solving Report

P1054 Equivalent expression

Topic description

Obviously after entering middle school, I learned algebraic expressions. One day, he encountered a very troublesome multiple-choice question. The question stem of this question first gives an algebraic expression, and then lists several options, each option is also an algebraic expression, the requirement of the question is to determine which algebraic expressions in the options are the same as the expressions in the question stem equivalent.

This problem is very troublesome to calculate by hand, because he is obviously very interested in computer programming, so he wonders if a computer can be used to solve this problem. Assuming you are Mingming, can you complete this task?

Each expression in this multiple-choice question satisfies the following properties:

1. The expression may contain only one variable 'a'. 2. The numbers appearing in the expression are all positive integers, and all are less than 10000. 3. Expressions can include four operations '+' (addition), '-' (subtraction), ' ' (multiplication), '^' (power), and parentheses '(', ')'. Parentheses have the highest precedence, followed by '^', then ' ', and finally '+' and '-'. '+' and '-' have the same precedence. Operations of the same priority are performed from left to right. (Note: Operators '+', '-', '*', '^' and parentheses '(', ')' are all English characters) 4. The power exponent can only be a positive integer between 1 and 10 (both inclusive). 5. Inside the expression, there may be some extra spaces at the beginning or end.

Here are some examples of reasonable expressions:

((a^1) ^ 2)^3,aa+a-a,((a+a)),9999+(a-a)a,1 + (a -1)^3,1^10^9……

Input and output format

Input format:

The first line of the input file gives the expression in the stem.

The second line is an integer n (2 <= n <= 26), indicating the number of options. After n lines, each line contains an expression in an option. The labels of these n options are A, B, C, D...

The length of the expressions in the input should not exceed 50 characters, and it is guaranteed that there are always expressions in the options that are equivalent to the expressions in the stem.

Output format:

The output file consists of a line containing a series of option labels indicating which options are equivalent to the expression in the header. The labels of the options are in alphabetical order with no spaces between them.


I really want to vomit ten liters of blood after writing this question. . .

I really want to vomit ten liters of blood after writing this question. . .

I really want to vomit ten liters of blood after writing this question. . .


Two points:

  1. The perfect algorithm is not easy to write, just provide some prime numbers as the value of a to be substituted into the calculation
  2. Infix expressions are converted to post (pre) infix expressions.

  • Infix expression to postfix expression

The stack s1 stores the number or operator, and s2 stores the operator

Scan from left to right

digital into s1

operator discussion

If the priority of the top of the s2 stack is lower than that of the incoming, we think it is legal (think about why it is not equal)

else pop s2 to s1 until legal

Parentheses need more judgment


Details of the imperfect algorithm:

  1. In order to avoid explosion ll, to mod a large prime number.

The prime number can't be too big, or it will still explode
, and it can't be too small, or the negative number module will have problems
(lucky number 1000000007)
, it can't be filmed every step, it will be very slow

  1. The value of a should be small, otherwise there may be problems

  2. The number of a cannot be more or less, otherwise there may be problems


Summary: Imperfect algorithms should be based on looking at faces, think more


code:

// luogu-judger-enable-o2
#include <cstdio>
#include <cstring>
#include <stack>
#define ll long long
using namespace std;
int n;
ll last[15],now[15];
int is[260];
ll pre[5]={5,7,11,2,3};
ll mod=1000000007;
char C[60];
void init()
{
    for(int i='0';i<='9';i++)
        is[i]=1;
    is[int('(')]=2;
    is[int('+')]=3;
    is[int('-')]=3;
    is[int('*')]=4;
    is[int('^')]=5;
    is[int(')')]=6;
    is[int('a')]=7;
}
int cnt;
void read()
{
    char c=getchar();
    while(!is[c]) c=getchar();
    cnt=-1;
    while(c!='\r')
    {
        if(is[c])
            C[++cnt]=c;
        c=getchar();
    }
}

struct node
{
    int k;//符号1还是数字0
    ll c;//数学或者AS码
    node(){}
    node(int k,ll c)
    {
        this->k=k;
        this->c=c;
    }
};

ll get_pow(ll n1,ll n2)
{
    ll nn=1;
    while(n2)
    {
        nn=nn*n1;
        if(nn>=mod)
            nn%=mod;
        n2--;
    }
    return nn;
}

stack <node > s1,s2;

bool get(char *now,int cnt,int flag)
{
    while(!s1.empty()) s1.pop();
    while(!s2.empty()) s2.pop();
    for(int k=0;k<=4;k++)
    {
        for(int i=0;i<=cnt;i++)
        {
            ll x=0;
            char c=*(now+i);
            if(is[c]==1)
            {
                while(is[c]==1&&i<=cnt) {x=x*10+c-'0';i++;c=*(now+i);}
                node tt(0,x);
                s1.push(tt);
                i--;
            }
            else if(is[c]==7)
            {
                node tt(0,pre[k]);
                s1.push(tt);
            }
            else if(is[c]==6)
            {
                while(!s2.empty())
                {
                    if(s2.top().k&&is[s2.top().c]==2)
                        break;
                    s1.push(s2.top());
                    s2.pop();
                }
                if(s2.empty())
                    return false;
                else
                    s2.pop();
            }
            else
            {
                node tt(1,c);
                while(!s2.empty()&&is[s2.top().c]>=is[c]&&s2.top().c!='('&&c!='(')
                {
                    s1.push(s2.top());
                    s2.pop();
                }
                s2.push(tt);
            }
        }
        while(!s2.empty())
        {
            if(is[s2.top().c]==2)
                return false;
            s1.push(s2.top());
            s2.pop();
        }
        while(!s1.empty())
        {
            s2.push(s1.top());
            //printf("%d ",s1.top().c);
            s1.pop();
        }
        //printf("\n");
        while(!s2.empty())
        {
            node tt=s2.top();
            s2.pop();
            if(tt.k)
            {
                ll t1=s1.top().c;
                s1.pop();
                ll t2=s1.top().c;
                s1.pop();
                ll t3;
                if(char(tt.c)=='+')
                    t3=t1+t2;
                else if(char(tt.c)=='-')
                    t3=t2-t1;
                else if(is[tt.c]==4)
                {
                    t3=t2*t1;
                    if(t3>=mod)
                        t3%=mod;
                }
                else if(is[tt.c]==5)
                    t3=get_pow(t2,t1);
                tt.c=t3;
                tt.k=0;
                s1.push(tt);
            }
            else
                s1.push(tt);
        }
        int ttt=s1.top().c%mod;
        if(flag)
            last[k]=s1.top().c%mod;
        else if(last[k]!=ttt)
            return false;
        s1.pop();
    }
    return true;
}

int main()
{
    init();
    read();
    get(C,cnt,1);
    char c=getchar();
    n=0;
    while(!is[c]) c=getchar();
    while(c!='\r') {n=n*10+c-'0';c=getchar();}
    for(int i=0;i<n;i++)
    {
        read();
        if(get(C,cnt,0))
            printf("%c",char(i+'A'));
    }
    return 0;
}

2018.4.29

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325383785&siteId=291194637