NOIP2005【等價表達式】

Description

明明進了中學之後,學到了代數表達式。有一天,他碰到一個很麻煩的選擇題。這個題目的題幹中首先給出了一個代數表達式,然後列出了若干選項,每個選項也是一個代數表達式,題目的要求是判斷選項中哪些代數表達式是和題幹中的表達式等價的。 這個題目手算很麻煩,因爲明明對計算機編程很感興趣,所以他想是不是可以用計算機來解決這個問題。假設你是明明,能完成這個任務嗎?   這個選擇題中的每個表達式都滿足下面的性質:

1.  表達式只可能包含一個變量‘a’。

2.  表達式中出現的數都是正整數,而且都小於10000。

3.  表達式中可以包括四種運算‘+’(加),‘-’(減),‘’(乘),‘^’(乘冪),以及小括號‘(’,‘)’。小括號的優先級最高,其次是‘^’,然後是‘’,最後是‘+’和‘-’。‘+’和‘-’的優先級是相同的。相同優先級的運算從左到右進行。(注意:運算符‘+’,‘-’,‘*’,‘^’以及小括號‘(’,‘)’都是英文字符)

4.  冪指數只可能是1到10之間的正整數(包括1和10)。

5.  表達式內部,頭部或者尾部都可能有一些多餘的空格。

下面是一些合理的表達式的例子:

((a^1) ^ 2)^3,aa+a-a,((a+a)),9999+(a-a)a,1 + (a -1)^3,1^10^9……  

Input Format

輸入文件equal.in的第一行給出的是題幹中的表達式。

第二行是一個整數n(2 <= n <= 26),表示選項的個數。後面n行,每行包括一個選項中的表達式。這n個選項的標號分別是A,B,C,D……

輸入中的表達式的長度都不超過50個字符,而且保證選項中總有表達式和題幹中的表達式是等價的。

Output Format

輸出文件equal.out包括一行,這一行包括一系列選項的標號,表示哪些選項是和題幹中的表達式等價的。選項的標號按照字母順序排列,而且之間沒有空格。

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

Hint

【數據規模】  

對於30%的數據,表達式中只可能出現兩種運算符‘+’和‘-’;

對於其它的數據,四種運算符‘+’,‘-’,‘*’,‘^’在表達式中都可能出現。

  對於全部的數據,表達式中都可能出現小括號‘(’和‘)’。

【題解】

個人覺得出題者的本意應該是要大家打分治或者棧判斷表達式係數是否相等從而判斷是否等價

本題解提供的做法是隨機算法+表達式求值

通過多次隨機出多個a值每次對給定的表達式求值若值不想等則表達式不等價,由於裏面次方數過大又懶得打高精度 就把表達式的值對一個大質數取模(比如1e9+7)

(隨機1000也不會超時吧,一般第一個值就把所有都排除了,很多人都是直接弄一個小質數就過了233)如果臉特別黑最後錯了的話 就老實的去打正解分治吧(這得有多臉黑)

至於表達式求值就通過兩個棧(數字棧和符號棧)以及符號運算優先級模擬實現(不會的自行參考代碼學習)

等博主哪天無聊再去打分治或者棧的做法的打法吧233

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#include <cmath>
#include <queue>
#include <time.h>
using namespace std;
long long a[55],b[55],c[55];
int i,j,k,l,m,n,ha,hb,hx,hy,t,x,y;
char sd[30][55],s[55];
long long Mod=1e9+7;
long long num(long long tt,long long yy)
  {
    long long ll;
  	for (ll=1;yy;yy--) 
	  ll*=tt,ll%=Mod;
  	return ll;
  }
long long work(int x,int k)
  {
  	int n,i,j,l;
    for (l=strlen(sd[k]);l>=0;l--) s[l]=sd[k][l];
    l=strlen(sd[k]);
  	ha=hb=0;
  	memset(a,0,sizeof(a));memset(b,0,sizeof(b));
  	for (i=0;i<l;)
  	  {
  	  	if (s[i]=='a') b[++hb]=x;
  	  	if (s[i]=='(') a[++ha]=0;
  	  	if (s[i]==')') 
  	  	  {
  	  	  	for(;a[ha]!=0;)
  	  	  	  {
  	  	  	  	if (a[ha]==4) b[hb-1]=num(b[hb-1],b[hb])%Mod,hb--;
  	  	  	  	if (a[ha]==3) b[hb-1]=(b[hb-1]*b[hb])%Mod,hb--;
  	  	  	    if (a[ha]==2) b[hb-1]=(b[hb-1]-b[hb])%Mod,hb--;
  	  	  	    if (a[ha]==1) b[hb-1]=(b[hb-1]+b[hb])%Mod,hb--;
  	  	  	    ha--;
  	  	  	  }
  	  	  	ha--;
  	  	  }
  	  	if (s[i]=='*'||s[i]=='-'||s[i]=='+'||s[i]=='^')
  	  	{
  	  	if (s[i]=='^') n=4;
  	  	if (s[i]=='*') n=3;
  	  	if (s[i]=='-') n=2;
  	  	if (s[i]=='+') n=1;
  	  
  	  	for (;n<=a[ha];) 
  	  	  {
  	  	  	if (a[ha]==4) b[hb-1]=num(b[hb-1],b[hb])%Mod,hb--;
  	  	  	if (a[ha]==3) b[hb-1]=(b[hb-1]*b[hb])%Mod,hb--;
  	  	  	if (a[ha]==2) b[hb-1]=(b[hb-1]-b[hb])%Mod,hb--;
  	  	  	if (a[ha]==1) b[hb-1]=(b[hb-1]+b[hb])%Mod,hb--;
  	  	  	ha--;
  	  	  }
  	  	ha++;a[ha]=n;
  	    }
  	    if (s[i]>='0'&&s[i]<='9')
  	      {
  	      	t=0;
  	      	for (;s[i]>='0'&&s[i]<='9';i++) t=t*10+s[i]-'0';
			i--;b[++hb]=t; 
		  }
  	  	i++;
  	  }
  	for(;a[ha]!=0;)
  	   {
  	  	  	if (a[ha]==4) b[hb-1]=num(b[hb-1],b[hb])%Mod,hb--;
  	  	  	if (a[ha]==3) b[hb-1]=(b[hb-1]*b[hb])%Mod,hb--;
  	  	  	if (a[ha]==2) b[hb-1]=(b[hb-1]-b[hb])%Mod,hb--;
  	  	  	if (a[ha]==1) b[hb-1]=(b[hb-1]+b[hb])%Mod,hb--;
  	  	  	ha--;
  	   }
  	if (b[1]>=0) return (b[1]);else return(b[1]+Mod);
  }
int main()
  {
  	gets(sd[0]);
  	scanf("%d\n",&n);
	for (i=1;i<=n;i++) gets(sd[i]);
	for (i=1;i<=20;i++)
	  {
	  	x= rand() % 10000;
	  	y=work(x,0);
	  	for (j=1;j<=n;j++)
	  	  if (!c[j]) if (work(x,j)!=y) c[j]=1;
	  }
	for (i=1;i<=n;i++)
	  if (!c[i]) printf("%c",i+'A'-1);
  }


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章