等价表达式(equal.pas/c/cpp)
【问题描述】
明明进了中学之后,学到了代数表达式。有一天,他碰到一个很麻烦的选择题。这个题目的题干中首先给出了一个代数表达式,然后列出了若干选项,每个选项也是一个代数表达式,题目的要求是判断选项中哪些代数表达式是和题干中的表达式等价的。
这个题目手算很麻烦,因为明明对计算机编程很感兴趣,所以他想是不是可以用计算机来解决这个问题。假设你是明明,能完成这个任务吗?
这个选择题中的每个表达式都满足下面的性质:
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……
【输入文件】
输入文件equal.in的第一行给出的是题干中的表达式。第二行是一个整数n(2 <= n <= 26),表示选项的个数。后面n行,每行包括一个选项中的表达式。这n个选项的标号分别是A,B,C,D……
输入中的表达式的长度都不超过50个字符,而且保证选项中总有表达式和题干中的表达式是等价的。
【输出文件】
输出文件equal.out包括一行,这一行包括一系列选项的标号,表示哪些选项是和题干中的表达式等价的。选项的标号按照字母顺序排列,而且之间没有空格。
【样例输入】
( a + 1) ^2
3
(a-1)^2+4*a
a + 1+ a
a^2 + 2 * a * 1 + 1^2 + 10 -10 +a -a
【样例输出】
AC
【数据规模】
对于30%的数据,表达式中只可能出现两种运算符‘+’和‘-’;
对于其它的数据,四种运算符‘+’,‘-’,‘*’,‘^’在表达式中都可能出现。
对于全部的数据,表达式中都可能出现小括号‘(’和‘)’。
s,st:string;
ans,e,g,i,k,x,n:longint;
a:array[1..26]of string;
c:array[1..26]of boolean;
procedure cutit(var ss:string); //删除空格
begin
while pos(' ',ss)<>0 do delete(ss,pos(' ',ss),1);
end;
function f(l,r:longint):longint;
var
kh,fh,i:longint;
begin
if l>r then exit;
kh:=0; //kh:括号层数
fh:=0; //fh:运算符的位置
for i:=r downto l do
begin
if st[i]=')' then inc(kh) else
if st[i]='(' then dec(kh);
if kh=0 then
begin
if (st[i]in['+','-']) then begin fh:=i; break;end else
if (st[i]='*')and((fh=0)or(st[fh]in['*','^'])) then fh:=i else
if (st[i]='^')and(fh=0)then fh:=i;
end;
end;
if fh=0 then //边界情况的处理
begin
if (st[l]='(')and(st[r]=')') then exit(f(l+1,r-1));{去掉多余的括弧}
if (st[r]=')')then exit(f(l,r-1));
if (st[l]='(')then exit(f(l+1,r));
if st[l]='a' then exit(x);
f:=0;
for i:=l to r do f:=f*10+ord(st[i])-ord('0');
end
else
begin //递归计算运算符两边
case st[fh]of
'+':exit((f(l,fh-1)+f(fh+1,r))mod 35111);
'-':exit((f(l,fh-1)-f(fh+1,r)+35111)mod 35111);
'*':exit((f(l,fh-1)*f(fh+1,r))mod 35111);
'^':begin
f:=1;
e:=f(l,fh-1);g:=f(fh+1,r);
for i:=1 to g do f:=f*e mod 35111;
end;
end;
end;
end;
begin
Assign(Input,'equal.in'); Reset(Input);
Assign(Output,'equal.out'); Rewrite(Output);
readln(s);
cutit(s);
readln(n);
for i:=1 to n do
begin
readln(a[i]);
cutit(a[i]); {删除多余空格}
end;
x:=9;
for k:=1 to 8 do {用8个数代替a}
begin
inc(x,2);
st:=s;
ans:=f(1,length(st)); {计算表达式的值}
for i:=1 to n do if not c[i] then
begin
st:=a[i];
if f(1,length(st))<>ans then c[i]:=true;
end;
end;
for i:=1 to n do
if not c[i] then write(chr(i+64));
writeln;
close(input); close(output);
end.