回 帖 发 新 帖 刷新版面

主题:帮我解题!《等价表达式》

第十一届全国青少年奥林匹克信息学联赛复赛提高组试题

等价表达式
(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%的数据,表达式中只可能出现两种运算符‘+’和‘-’;
对于其它的数据,四种运算符‘+’,‘-’,‘*’,‘^’在表达式中都可能出现。

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

回复列表 (共3个回复)

沙发

const
  dvd = 3031; max = 26; maxn = 55;
  fs : string[6] = '()+-*^';
var
  st      : array[0..max] of string[maxn];
  f       : array[1..max] of boolean;
  i,j,k,n : integer;
  r       : longint;

function ff(x,l : longint) : longint;
var
  s       : string;
  a       : array[1..maxn]of longint;
  m,i,j,k : integer;
  flag    : boolean;
begin
  s := st[l];   {(=dvd+1 ; )=dvd+2 ; +=dvd+3 ; -=dvd+4 ; *=dvd+5 ; ^=dvd+6 }
  i := 1; j := 1;
  while i <= length(s) do
    if pos(s[i],fs) > 0
    then begin a[j] := dvd+pos(s[i],fs); inc(j); inc(i); continue; end
    else begin
           if s[i] = 'a'
             then begin a[j]:=x; inc(i); end
             else begin
                    m := 0;
                    while (s[i] in ['0'..'9']) and (i<=length(s)) do
                      begin m := m*10+ord(s[i])-48; inc(i); end;
                    a[j] := m mod dvd;
                  end;
           while true do begin
             if j = 1 then begin inc(j); break; end;
             if (a[j-1] = dvd+1) then
               if s[i] = ')'
                 then begin a[j-1]:=a[j]; j:=j-1; inc(i); continue; end
                 else begin inc(j); break; end;
             if (a[j-1]-dvd<pos(s[i],fs))and(i<length(s))
               then begin inc(j); break; end
               else begin
                      case a[j-1]-dvd of
                        3 : a[j-2]:=a[j-2]+a[j];
                        4 : a[j-2]:=a[j-2]-a[j];
                        5 : a[j-2]:=a[j-2]*a[j];
                        6 : begin
                              m := 1;
                              for k := 1 to a[j] do m := (m*a[j-2]) mod dvd;
                              a[j-2] := m;
                            end;
                      end;
                      j := j-2; a[j] := (a[j] mod dvd+dvd) mod dvd;
                    end;
           end;
         end;
  ff := a[1];
end;

begin
  assign(input,'equal.in'); reset(input);
  assign(output,'equal.out'); rewrite(output);
  readln(st[0]);
  while pos(' ',st[0]) > 0 do delete(st[0],pos(' ',st[0]),1);
  if (pos('^',st[0]) = 0) and (pos('*',st[0]) = 0) then k := 1 else k := 9;
  readln(n);
  for i := 1 to n do begin
    readln(st[i]); f[i] := true;
    while pos(' ',st[i]) > 0 do delete(st[i],pos(' ',st[i]),1);
  end;
  for i := 0 to k do begin
    r := ff(i,0);
    for j := 1 to n do
      if f[j] then f[j] := (ff(i,j)=r);
  end;
  for i := 1 to n do if f[i] then write(chr(64+i));
  writeln;
  close(input); close(output);
end.

板凳

[em1][em2][em3][em4][em5][em6][em7][em8][em9][em10][em11][em12][em13][em14][em15][em16][em17][em19][em20][em27][em28][em29][em30][em26][em25][em24][em23][em22][em21][em55][em45][em70]
const
  dvd = 3031; max = 26; maxn = 55;
  fs : string[6] = '()+-*^';
var
  st      : array[0..max] of string[maxn];
  f       : array[1..max] of boolean;
  i,j,k,n : integer;
  r       : longint;

function ff(x,l : longint) : longint;
var
  s       : string;
  a       : array[1..maxn]of longint;
  m,i,j,k : integer;
  flag    : boolean;
begin
  s := st[l];   {(=dvd+1 ; )=dvd+2 ; +=dvd+3 ; -=dvd+4 ; *=dvd+5 ; ^=dvd+6 }
  i := 1; j := 1;
  while i <= length(s) do
    if pos(s[i],fs) > 0
    then begin a[j] := dvd+pos(s[i],fs); inc(j); inc(i); continue; end
    else begin
           if s[i] = 'a'
             then begin a[j]:=x; inc(i); end
             else begin
                    m := 0;
                    while (s[i] in ['0'..'9']) and (i<=length(s)) do
                      begin m := m*10+ord(s[i])-48; inc(i); end;
                    a[j] := m mod dvd;
                  end;
           while true do begin
             if j = 1 then begin inc(j); break; end;
             if (a[j-1] = dvd+1) then
               if s[i] = ')'
                 then begin a[j-1]:=a[j]; j:=j-1; inc(i); continue; end
                 else begin inc(j); break; end;
             if (a[j-1]-dvd<pos(s[i],fs))and(i<length(s))
               then begin inc(j); break; end
               else begin
                      case a[j-1]-dvd of
                        3 : a[j-2]:=a[j-2]+a[j];
                        4 : a[j-2]:=a[j-2]-a[j];
                        5 : a[j-2]:=a[j-2]*a[j];
                        6 : begin
                              m := 1;
                              for k := 1 to a[j] do m := (m*a[j-2]) mod dvd;
                              a[j-2] := m;
                            end;
                      end;
                      j := j-2; a[j] := (a[j] mod dvd+dvd) mod dvd;
                    end;
           end;
         end;
  ff := a[1];
end;

begin
  assign(input,'equal.in'); reset(input);
  assign(output,'equal.out'); rewrite(output);
  readln(st[0]);
  while pos(' ',st[0]) > 0 do delete(st[0],pos(' ',st[0]),1);
  if (pos('^',st[0]) = 0) and (pos('*',st[0]) = 0) then k := 1 else k := 9;
  readln(n);
  for i := 1 to n do begin
    readln(st[i]); f[i] := true;
    while pos(' ',st[i]) > 0 do delete(st[i],pos(' ',st[i]),1);
  end;
  for i := 0 to k do begin
    r := ff(i,0);
    for j := 1 to n do
      if f[j] then f[j] := (ff(i,j)=r);
  end;
  for i := 1 to n do if f[i] then write(chr(64+i));
  writeln;
  close(input); close(output);
end.

3 楼


程序不错啊,不过只能得30分.官方测试数据中,第二组数据漏了个,后面六组数据不能通过,不是超时,是运行错误216。

我来回复

您尚未登录,请登录后再回复。点此登录或注册