1107 等价表达式



 

2005年NOIP全国联赛提高组





 时间限制: 1 s



 空间限制: 128000 KB



 题目等级 : 钻石 Diamond


​题解​


 查看运行结果


 


 






题目描述 Description



明明进了中学之后,学到了代数表达式。有一天,他碰到一个很麻烦的选择题。这个题目的题干中首先给出了一个代数表达式,然后列出了若干选项,每个选项也是一个代数表达式,题目的要求是判断选项中哪些代数表达式是和题干中的表达式等价的。


这个题目手算很麻烦,因为明明对计算机编程很感兴趣,所以他想是不是可以用计算机来解决这个问题。假设你是明明,能完成这个任务吗?


这个选择题中的每个表达式都满足下面的性质:

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……



输入描述 Input Description



输入第一行给出的是题干中的表达式。第二行是一个整数n(2<=n<=26),表示选项的个数。后面n行,每行包括一个选项中的表达式。这n个选项的标号分别是A,B,C,D……


输入中的表达式的长度都不超过50个字符,而且保证选项中总有表达式和题干中的表达式是等价的。



输出描述 Output Description



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



样例输入 Sample Input



(a+1)^2

3

(a-1)^2+4*a

a+1+a

a^2+2*a*1+1^2+10-10+a-a



样例输出 Sample Output



AC



数据范围及提示 Data Size & Hint



【数据规模】

对于30%的数据,表达式中只可能出现两种运算符‘+’和‘-’;

对于其它的数据,四种运算符‘+’,‘-’,‘*’,‘^’在表达式中都可能出现。

对于全部的数据,表达式中都可能出现小括号‘(’和‘)’。

思路:带入几个数,如果答案相同,则基本一致。

这个题目思路很简单,但是有很多细节,坑死人了。



#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 100
#define mod 10007
using namespace std;
int tmp[MAXN];
int top1,top2,len,n;
char s[MAXN],bns[MAXN],c[MAXN];
long long stack1[MAXN],stack2[MAXN],stack3[MAXN];
int pow(int a,int b){
int sum=a;
for(int i=2;i<=b;i++)
sum=(sum*a+mod)%mod;
return sum;
}
void work(){
int m1=stack1[top1],n1=stack1[top1-1],m2=stack2[top1],n2=stack2[top1-1],m3=stack3[top1],n3=stack3[top1-1];
top1--;
//printf("%d",top1);
if(bns[top2]=='+'){
stack1[top1]=(n1+m1+mod)%mod;
stack2[top1]=(n2+m2+mod)%mod;
stack3[top1]=(n3+m3+mod)%mod;
}
else if(bns[top2]=='-'){
stack1[top1]=(n1-m1+mod)%mod;
stack2[top1]=(n2-m2+mod)%mod;
stack3[top1]=(n3-m3+mod)%mod;
}
else if(bns[top2]=='*'){
stack1[top1]=(n1*m1+mod)%mod;
stack2[top1]=(n2*m2+mod)%mod;
stack3[top1]=(n3*m3+mod)%mod;
}
else if(bns[top2]=='^'){
stack1[top1]=pow(n1,m1);
stack2[top1]=pow(n2,m2);
stack3[top1]=pow(n3,m3);
}
top2--;
//printf("%d",top2);
}
void judge(){
int num=0;
for(int i=0;i<len;i++){
if(s[i]=='a'){
stack1[++top1]=3;
stack2[top1]=7;
stack3[top1]=13;
}
else if(s[i]>='0'&&s[i]<='9')
num=num*10+s[i]-'0';
else{
if(num!=0){
stack1[++top1]=num;
stack2[top1]=num;
stack3[top1]=num;
num=0;
}
if(tmp[s[i]]==0) continue;
if(s[i]=='('||s[i]!=')'&&top2==0) bns[++top2]=s[i];
else{
if(tmp[s[i]]<tmp[bns[top2]])
if(s[i]!=')') bns[++top2]=s[i];
else{
while(bns[top2]!='('&&top2>0) work();
if(bns[top2]=='(') top2--;
}
else{
while(tmp[s[i]]>=tmp[bns[top2]]&&top2>0) work();
if(s[i]!=')') bns[++top2]=s[i];
}
}
}
}
if(num!=0){
stack1[++top1]=num;
stack2[top1]=num;
stack3[top1]=num;
num=0;
}
while(top2>0) work();
}
int main(){
tmp[41]=1;tmp[94]=2;tmp[40]=5;
tmp[42]=tmp[47]=3;tmp[43]=tmp[45]=4;
scanf("%[^\n]",s);
len=strlen(s);
judge();
long long num1=stack1[1];
long long num2=stack2[1];
long long num3=stack3[1];
scanf("%d",&n);
for(int i=1;i<=n;i++){
memset(s,0,sizeof(s));
scanf("%c",&c);
scanf("%[^\n]",s);
len=strlen(s);
top1=top2=0;
judge();
if(num1==stack1[1]%mod&&num2==stack2[1]%mod&&num3==stack3[1]%mod)
cout<<char(i+64);
}
}


 


细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。 雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。