等价表达式 (codevs 1107)题解

【问题描述】

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

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

这个选择题中的每个表达式都满足下面的性质:
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……

【样例输入】

     (a+1)^2
     3
     (a-1)^2+4*a
     a+1+a
     a^2+2*a*1+1^2+10-10+a-a

【样例输出】

     AC

【解题思路】

     本题为NOIP2005提高组第四题,求两个表达式是否等价,其实就是看两个表达式的值是否相等,因此,我们将a换为随机化的数,多次随机化的数产生的结果都相等的话,就说明两个表达式等价,便输出表达式的选项,求表达式的值,自然就是用栈来解决,详见NOIP2013普及组第二题。我在这道题上用了两个总过程,一个建栈,一个计算

【代码实现】

  1 type arr=array[1..2000] of char;
  2      arr2=array[1..2000] of extended;
  3 var ii,jj,n,c1,c2:longint;
  4     tag:boolean;
  5     x1,x2,x3:extended;
  6     c:char;
  7     st,a,e:string;
  8 function pop(var stack:arr; var t:longint):char;
  9 begin
 10  pop:=stack[t];
 11  dec(t);
 12 end;
 13 function top(var stack:arr; var t:longint):char;
 14 begin
 15  top:=stack[t];
 16 end;
 17 procedure push(var stack:arr; ch:char; var t:longint);
 18 begin
 19  inc(t);
 20  stack[t]:=ch;
 21 end;
 22 procedure create(var x,y:string);//建栈
 23 var  s:arr;
 24      tp,i,j,k:longint;
 25 begin
 26  x:=x+'@';i:=1;tp:=0;y:='';
 27  while x[i]<>'@' do
 28   begin
 29    case x[i] of
 30     '0'..'9':
 31      begin
 32       while (x[i]>='0')and(x[i]<='9') do
 33        begin
 34         y:=y+x[i];
 35         inc(i);
 36        end;
 37       dec(i);
 38       y:=y+'.';
 39      end;
 40     'a':y:=y+'a';
 41     '(':push(s,'(',tp);
 42     ')':
 43      begin
 44       if tp>0 then
 45        begin
 46         c:=top(s,tp);
 47         while c<>'(' do
 48          begin
 49           y:=y+c;
 50           c:=pop(s,tp);
 51           if tp>0 then
 52            c:=top(s,tp)
 53           else
 54            break;
 55          end;
 56        end;
 57       if (tp>0)and(c='(')then
 58        c:=pop(s,tp);
 59      end;
 60     '+','-':
 61      begin
 62       if tp>0 then
 63        begin
 64         c:=top(s,tp);
 65         while c<>'(' do
 66          begin
 67           y:=y+c;
 68           c:=pop(s,tp);
 69           if tp>0 then
 70            c:=top(s,tp)
 71           else
 72            break;
 73          end;
 74        end;
 75       push(s,x[i],tp);
 76      end;
 77     '*','/':
 78      begin
 79       if tp>0 then
 80        begin
 81         c:=top(s,tp);
 82         while (c<>'(')and(c<>'+')and(c<>'-') do
 83          begin
 84           y:=y+c;
 85           c:=pop(s,tp);
 86           if tp>0 then
 87            c:=top(s,tp)
 88           else
 89           break;
 90          end;
 91        end;
 92       push(s,x[i],tp);
 93      end;
 94     '^':
 95      begin
 96       if tp>0 then
 97        begin
 98         c:=top(s,tp);
 99         while c='^' do
100          begin
101           y:=y+c;
102           c:=pop(s,tp);
103           if tp>0 then
104            c:=top(s,tp)
105           else
106            break;
107          end;
108        end;
109       push(s,x[i],tp);
110      end;
111     end;
112    inc(i);
113   end;
114  while tp>0 do
115   y:=y+pop(s,tp);
116  y:=y+'@';
117 end;
118 function pop2(var stack:arr2;var tp:longint):extended;
119 begin
120  pop2:=stack[tp];
121  dec(tp);
122 end;
123 function top2(var stack:arr2; var tp:longint):extended;
124 begin
125  top2:=stack[tp];
126 end;
127 procedure push2(var stack:arr2; num:extended; var tp:longint);
128 begin
129  inc(tp);
130  stack[tp]:=num;
131 end;
132 function chu(x,y:extended):extended;
133 begin
134  if y=0 then
135   chu:=-maxlongint
136  else
137   chu:=x/y;
138 end;
139 function cf(x,y:extended):extended;
140 var i:longint;
141 begin
142  cf:=1;
143  for i:=1 to round(y) do
144   cf:=cf*x;
145 end;
146 function work(x:string;v:extended):extended;//求表达式的值
147 var s:arr2;
148     i,j,tp:longint;
149     k,w1,w2:extended;
150 begin
151  i:=1;tp:=0;
152  while x[i]<>'@' do
153   begin
154    case x[i] of
155     '0'..'9':
156      begin
157       k:=0;
158       while x[i]<>'.' do
159        begin
160         k:=k*10+ord(x[i])-48;
161         inc(i);
162        end;
163       push2(s,k,tp);
164      end;
165     'a':
166      begin
167       k:=v;
168       push2(s,k,tp);
169      end;
170     '+':push2(s,pop2(s,tp)+pop2(s,tp),tp);
171     '-':
172      begin
173       w2:=pop2(s,tp);
174       w1:=pop2(s,tp);
175       push2(s,w1-w2,tp);
176      end;
177     '*':push2(s,pop2(s,tp)*pop2(s,tp),tp);
178     '/'://可能除以0,需要判断
179      begin
180       w2:=pop2(s,tp);
181       w1:=pop2(s,tp);
182       k:=chu(w1,w2);
183       if k=-maxlongint then
184        exit(-maxlongint)
185       else
186        push2(s,k,tp);
187      end;
188     '^':
189      begin
190       w2:=pop2(s,tp);
191       w1:=pop2(s,tp);
192       push2(s,cf(w1,w2),tp);
193      end;
194    end;
195   inc(i);
196  end;
197  work:=pop2(s,tp);
198 end;
199 procedure k;
200 var st1,st2,s1,s2:string;
201     ch:char;
202     r,u:longint;
203     t1,t2:extended;
204 begin
205  readln(e);
206  while pos(chr(32),e)<>0 do
207   delete(e,pos(chr(32),e),1);
208  create(e,a);
209  tag:=true;//判断两个表达式是否相等
210  c1:=0;
211  c2:=0;
212  for jj:=1 to 20 do
213   begin
214    x3:=random;
215    x1:=work(st,x3);
216    x2:=work(a,x3);
217    if (x1=1)or(x2=1) then
218     begin
219      if abs(x1-x2)<1e-10 then
220       continue
221      else
222       begin
223        tag:=false;
224        break;
225       end;
226     end;
227    if (x1=-maxlongint)or(x2=-maxlongint) then
228     begin
229      if x1=-maxlongint then
230       inc(c1);
231      if x2=-maxlongint then
232       inc(c2);
233      continue;
234     end
235    else
236     begin
237      str(x1,st1);
238      str(x2,st2);
239      s1:=copy(st1,1,10);
240      s2:=copy(st2,1,10);
241      t1:=ln(abs(x1));
242      t2:=ln(abs(x2));
243      if not((x1=x2)or(((x1>0)and(x2>0)or(x1<0)and(x2<0))and(round(t1)=round(t2))and(s1=s2))) then 这里是一个很重要的判断是否相等的句子,可以自行思考一下
244       begin
245        tag:=false;
246        break;
247       end;
248     end;
249   end;
250  if (c1=0)and(c2>0)or(c1>0)and(c2=0) then
251   tag:=false;
252  if tag then 
253   write(chr(ii+64));
254 end;
255 begin
256  randomize;//随机化
257  readln(e);
258  while pos(chr(32),e)<>0 do
259   delete(e,pos(chr(32),e),1);//数据有坑,无缘无故会有许多多余的空格
260  create(e,st);
261  readln(n);
262  for ii:=1 to n do
263   begin
264    if ii=14 then
265     n:=n;
266    k;
267   end;
268  writeln;
269 end.

 

你可能感兴趣的:(等价表达式 (codevs 1107)题解)