等价表达式 (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.

 

你可能感兴趣的:(code)