NOIP2005 等价表达式

来源:互联网 发布:淘宝店铺收藏链接生成 编辑:程序博客网 时间:2024/05/29 02:30

传送门

题目

明明进了中学之后,学到了代数表达式。有一天,他碰到一个很麻烦的选择题。这个题目的题干中首先给出了一个代数表达式,然后列出了若干选项,每个选项也是一个代数表达式,题目的要求是判断选项中哪些代数表达式是和题干中的表达式等价的。
这个题目手算很麻烦,因为明明对计算机编程很感兴趣,所以他想是不是可以用计算机来解决这个问题。假设你是明明,能完成这个任务吗?
这个选择题中的每个表达式都满足下面的性质:
1. 表达式只可能包含一个变量‘a’。
2. 表达式中出现的数都是正整数,而且都小于10000。
3. 表达式中可以包括四种运算‘+’(加),‘-’(减),‘’(乘),‘^’(乘幂),以及小括号‘(’,‘)’。小括号的优先级最高,其次是‘^’,然后是‘’,最后是‘+’和‘-’。‘+’和‘-’的优先级是相同的。相同优先级的运算从左到右进行。(注意:运算符‘+’,‘-’,‘*’,‘^’以及小括号‘(’,‘)’都是英文字符)
4. 幂指数只可能是1到10之间的正整数(包括1和10)。
5. 表达式内部,头部或者尾部都可能有一些多余的空格。
下面是一些合理的表达式的例子:
((a^1) ^ 2)^3,a*a+a-a,((a+a)),9999+(a-a)*a,1 + (a -1)^3,1^10^9……
对于30%的数据,表达式中只可能出现两种运算符‘+’和‘-’;
对于其它的数据,四种运算符‘+’,‘-’,‘*’,‘^’在表达式中都可能出现。
对于全部的数据,表达式中都可能出现小括号‘(’和‘)’。
格式
输入格式

输入的第一行给出的是题干中的表达式。第二行是一个整数n(2 <= n <= 26),表示选项的个数。后面n行,每行包括一个选项中的表达式。这n个选项的标号分别是A,B,C,D……
输入中的表达式的长度都不超过50个字符,而且保证选项中总有表达式和题干中的表达式是等价的。
输出格式

输出包括一行,这一行包括一系列选项的标号,表示哪些选项是和题干中的表达式等价的。选项的标号按照字母顺序排列,而且之间没有空格。

过程

昨天老师让我们练习这道题,于是我按照夏令营课件上的思路写了一份很优(zhì)美(zhàng)的代码。其实完全是乱搞的
写完后我自己测试了n组数据,都是对的,然而当我提交到vijos上以后,结果是AC×8+WA×2。我又换了几个用来代替’a’的质数和用来取模的数,成绩是70~80不等。当天晚上我将代码提交到教师机上的时候,我本来还希望能得80分,但是评测结果又对我的希望进行了折半处理。
第二天重新修改程序,我对着程序上上下下怎么也没找出错误来,然而同学替我找出了一个制杖错误:表达式里面是有减法的,当我们对数据取模以后有可能出现一个小的余数去减一个大的余数的情况,于是产生了负数,并导致栈顶指针不断减1直至为负。解决办法:先加一遍取模的数再取模,就能预防出现负数的情况。

代码:

#include<cstdio>#include<cstring>#define LL long longconst int M=1e9+7;LL n,i,p,topn,topf,len,k;char a[51];LL num[51];char f[51];LL t[11]={0,41,71,83,91,101};LL ans[11];char c[51];LL quickpow(LL a,LL b,LL p){    LL s=1;    a%=p;    for(;b;b=b>>1,a=(a*a)%p)      if(b&1) s=(s*a)%p;    return s;}LL level(char c){    if(c=='(') return 0;    if(c=='+'||c=='-') return 1;    if(c=='*'||c=='/') return 2;    if(c=='^') return 3;    return 0;}void work(){    LL x=num[topn--];    LL y=num[topn--];    char c=f[topf--];    if(c=='+') num[++topn]=(x+y)%M;    else if(c=='-') num[++topn]=(y-x+M)%M;//QAQ    else if(c=='*') num[++topn]=(x*y)%M;    else if(c=='^') num[++topn]=quickpow(y,x,M);}void getnum(char a[],LL &p){    LL t=0;    while(a[p]>='0'&&a[p]<='9')       t=(t*10+a[p++]-48)%M;    num[++topn]=t;}void push(LL n){    num[++topn]=t[n];}LL solve(char a[],LL i){    p=topf=topn=0;    len=strlen(a);    while(p<=len-1)      if(a[p]>='0'&&a[p]<='9') getnum(a,p);      else if(a[p]==' ') p++;      else if(a[p]=='+'||a[p]=='-'||a[p]=='*'||a[p]=='/'||a[p]=='^')             if(level(a[p])>level(f[topf])) f[++topf]=a[p++];             else             {                while(level(a[p])<=level(f[topf])) work();                f[++topf]=a[p++];             }      else if(a[p]=='a')      {        push(i);        p++;      }      else if(a[p]=='(') f[++topf]=a[p++];      else if(a[p]==')')      {        while(f[topf]!='(')          work();        topf--;        p++;      }    while(topn!=1) work();    return num[1];}main(){    freopen("equal.in","r",stdin);    freopen("equal.out","w",stdout);    gets(a);    for(i=1;i<=5;i++)      ans[i]=solve(a,i);    scanf("%d\n",&n);    for(k=1;k<=n;k++)    {        gets(c);        bool b=1;        for(i=1;i<=5;i++)          if(solve(c,i)!=ans[i])          {            b=0;            break;          }        if(b) putchar('A'+k-1);    }}
0 0
原创粉丝点击