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);
  }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值