1107 等价表达式

1107 等价表达式

2005年NOIP全国联赛提高组

时间限制: 1 s

空间限制: 128000 KB

题目等级 : 钻石 Diamond

题解

查看运行结果

题目描述 Description

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

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

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

输入描述 Input Description

输入第一行给出的是题干中的表达式。第二行是一个整数n(2<=n<=26),表示选项的个数。后面n行,每行包括一个选项中的表达式。这n个选项的标号分别是A,B,C,D……

输入中的表达式的长度都不超过50个字符,而且保证选项中总有表达式和题干中的表达式是等价的。

输出描述 Output Description

输出包括一行,这一行包括一系列选项的标号,表示哪些选项是和题干中的表达式等价的。选项的标号按照字母顺序排列,而且之间没有空格。

样例输入 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

数据范围及提示 Data Size & Hint

【数据规模】
对于30%的数据,表达式中只可能出现两种运算符‘+’和‘-’;
对于其它的数据,四种运算符‘+’,‘-’,‘*’,‘^’在表达式中都可能出现。
对于全部的数据,表达式中都可能出现小括号‘(’和‘)’。

分类标签 Tags 点此展开

编程能力题 大陆地区 NOIP全国联赛提高组 2005年

题解:

表达式计算

就是压栈处理;

设a为一个质数,模数为另一个质数,然后暴力算多项式的答案,如果答案相等就认为两个多项式相等。

这种hash有出错概率的题为什么还是要用hash呢?因为出错的概率实在太小了,a和模数的值取得好出题人根本没法卡。

(不一定非要取3、4次质数,主要是rp)

注意有空格。

裸的表达式计算

#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
#define N 256
int num[N],p=1,i,z;
char symbol[N],s[N],t[N],ans[N];
inline void push(){
    symbol[++p]=s[i];
}
inline void pop(){
    switch(symbol[p--]){
        case ‘^‘:num[p]=pow(num[p],num[p+1]);break;
        case ‘+‘:num[p]+=num[p+1];break;
        case ‘-‘:num[p]-=num[p+1];break;
        case ‘*‘:num[p]*=num[p+1];break;
        case ‘/‘:num[p]/=num[p+1];break;
    }
}
inline bool can(){
    if((s[i]==‘+‘||s[i]==‘-‘)&&symbol[p]!=‘(‘) return 1;
    if(s[i]==‘^‘&&symbol[p]==‘^‘) return 1;
    if((s[i]==‘*‘||s[i]==‘/‘)&&(symbol[p]==‘*‘||symbol[p]==‘/‘)) return 1;
    return 0;
}
inline void deal(){
    gets(s);
    int len=strlen(s);
    s[len]=‘)‘;symbol[p]=‘(‘;
    while(i<len){
        while(s[i]==‘(‘) push(),i++;
        int x(0);
        while(s[i]>=‘0‘&&s[i]<=‘9‘) x=x*10+s[i++]-‘0‘;
        num[p]=x;
        do{
            if(s[i]==‘)‘){
                while(symbol[p]!=‘(‘) pop();
                num[--p]=num[p+1];
            }
            else{
                while(can()) pop();
                push();
            }
            i++;
        }while(i<len&&s[i-1]==‘)‘);
    }
}
int main(){
    deal();
    printf("%d\n",num[0]);
    return 0;
}

本题AC代码:

#include<cstdio>
#include<cstring>
using namespace std;
#define ll long long
const int N=10003;
const int a=10007;
const int p=100007;
char s[N],c[N],sym[N];
int m,num[N],yxj[N],topnum,topch;
int get(char ch){
    if(ch==‘+‘||ch==‘-‘) return 1;
    if(ch==‘*‘) return 2;
    if(ch==‘^‘) return 3;
}
int ipow(int a,int b){
    ll t=1;
    for(int i=1;i<=b;i++)
        t=t*a%p;
    return (int)t;
}
int cal(char ch,int a,int b){
    switch(ch){
        case ‘^‘:return ipow(a,b);break;
        case ‘+‘:return (a+b)%p;break;
        case ‘-‘:return (a-b+p)%p;break;
        case ‘*‘:return (int)(1ll*a*b%p);break;
    }
}
bool can(char ch){
    return (ch==‘+‘||ch==‘-‘||ch==‘*‘||ch==‘^‘||ch==‘(‘||ch==‘)‘);
}
int deal() {
    int len=strlen(s),tmp=0,j=100,k;
    c[0]=‘ ‘;
    for(int i=0;i<len;++i)
        if(s[i]!=‘ ‘) c[++tmp]=s[i];
    c[tmp+1]=‘ ‘;
    len=tmp;tmp=1;topnum=topch=0;
    while(tmp<=len) {
        if(can(c[tmp])){
            if(c[tmp]==‘(‘) j+=10;
            else if(c[tmp]==‘)‘) j-=10;
            else{
                k=get(c[tmp]);
                while(topch&&yxj[topch]>=k+j) {
                    num[topnum-1]=cal(sym[topch],num[topnum-1],num[topnum]);
                    --topnum;--topch;
                }
                sym[++topch]=c[tmp];yxj[topch]=k+j;
            }
            ++tmp;
        }
        else{
            if(c[tmp]==‘a‘) num[++topnum]=a,++tmp;
            else{
                k=0;
                for(;c[tmp]>=‘0‘ && c[tmp]<=‘9‘ && tmp<=len;++tmp)k=k * 10+c[tmp]-‘0‘;
                num[++topnum]=k;
            }
        }
    }
    while(topch){
        num[topnum-1]=cal(sym[topch],num[topnum-1],num[topnum]);
        --topnum;--topch;
    }
    return num[1];
}
int main() {
    gets(s);
    int res=deal();
    scanf("%d\n",&m);
    for(int i=1;i<=m;++i){
        gets(s);
        int now=deal();
        if(now==res) putchar(64+i);
    }
    puts("");
    return 0;
}
时间: 2024-10-06 00:16:58

1107 等价表达式的相关文章

数据结构--栈 codevs 1107 等价表达式

codevs 1107 等价表达式 2005年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 明明进了中学之后,学到了代数表达式.有一天,他碰到一个很麻烦的选择题.这个题目的题干中首先给出了一个代数表达式,然后列出了若干选项,每个选项也是一个代数表达式,题目的要求是判断选项中哪些代数表达式是和题干中的表达式等价的. 这个题目手算很麻烦,因为明明对计算机编程很感兴趣,所以他想是不是可以用计算机来解决这

[Codevs 1107][NOIP 1107]等价表达式

题目连接:http://codevs.cn/problem/1107/ 一道很神奇的题目.对于算术表达式一类的问题,可以采用编译原理里的后缀表达式的方式来做,具体做法是分别维护两个栈,一个栈里保存表达式里的数字,另一个栈里保存表达式里的运算符,给每种运算符一个优先级,我们要维护这个栈的单调性,每次读入运算符中的数字或运算符,读入的是运算符时,若这个运算符比栈顶的运算符优先级低,就弹出栈顶元素,把栈顶的运算符和数字栈里栈顶的两个数字拿出来做一次运算,运算结果再入数字栈,直到运算符栈的栈顶元素优先级

等价表达式

栈的经典题目,开两个栈,一个存符号,一个存数字: 分情况讨论: 1.如果当前读到的运算符优先级小于栈顶,就进行一次运算,直到大于等于: 2.如果读到数字用类似读入优化的方法读入进来: 3.如果当前符号为"("则直接入栈: 4.如果当前符号为")"则进行运算直到碰到"(": 5.小技巧 在式子开头加"(",末尾加")": 6.遇到a,让a等于质数: 7.多次取模,因为有可能爆long long,模不同的质数,

和指针相关的两个特殊运算符,和相关的等价表达式

和指针相关的两个特殊运算符: 一."&" 取地址运算符,通过&运算符可以取出普通变量的地址: 二."*"  有两种意义: 1.  为指针标志: 是否为指针标志主要看前面是否有类型,此处有一个int 2.  为指针运算符:    在等号右面为取值.*可以取出指针变量所指向的普通变量的值.   在等号左面为赋值.*可以将指针变量所指向的普通变量的值,修改为其他. 3.  为乘法运算符.当且仅当左右的都为变量时.略. 如 int a, b =20, c=3

NOIP2005 等价表达式 解题报告

明明进了中学之后,学到了代数表达式.有一天,他碰到一个很麻烦的选择题.这个题目的题干中首先给出了一个代数表达式,然后列出了若干选项,每个选项也是一个代数表达式,题目的要求是判断选项中哪些代数表达式是和题干中的表达式等价的. 这个题目手算很麻烦,因为明明对计算机编程很感兴趣,所以他想是不是可以用计算机来解决这个问题.假设你是明明,能完成这个任务吗? 这个选择题中的每个表达式都满足下面的性质: 1.  表达式只可能包含一个变量‘a’. 2.  表达式中出现的数都是正整数,而且都小于10000. 3.

等价表达式(noip2005)

3.等价表达式 [问题描述]    兵兵班的同学都喜欢数学这一科目,中秋聚会这天,数学课代表给大家出了个有关代数表达式的选择题.这个题目的题干中首先给出了一个代数表达式,然后列出了若干选项,每个选项也是一个代数表达式,题目的要求是判断选项中哪些代数表达式是和题干中的表达式等价的.    这个题目手算很麻烦,因为数学课代表对计算机编程很感兴趣,所以他想是不是可以用计算机来解决这个问题.假设你是数学课代表,能完成这个任务吗? 这个选择题中的每个表达式都满足下面的性质: 1. 表达式只可能包含一个变量

等价表达式(codevs 1107 答案错误)

题目描述 Description 明明进了中学之后,学到了代数表达式.有一天,他碰到一个很麻烦的选择题.这个题目的题干中首先给出了一个代数表达式,然后列出了若干选项,每个选项也是一个代数表达式,题目的要求是判断选项中哪些代数表达式是和题干中的表达式等价的. 这个题目手算很麻烦,因为明明对计算机编程很感兴趣,所以他想是不是可以用计算机来解决这个问题.假设你是明明,能完成这个任务吗? 这个选择题中的每个表达式都满足下面的性质:1.表达式只可能包含一个变量‘a’.2.表达式中出现的数都是正整数,而且都

等价表达式 (codevs 1107)题解

[问题描述] 明明进了中学之后,学到了代数表达式.有一天,他碰到一个很麻烦的选择题.这个题目的题干中首先给出了一个代数表达式,然后列出了若干选项,每个选项也是一个代数表达式,题目的要求是判断选项中哪些代数表达式是和题干中的表达式等价的. 这个题目手算很麻烦,因为明明对计算机编程很感兴趣,所以他想是不是可以用计算机来解决这个问题.假设你是明明,能完成这个任务吗? 这个选择题中的每个表达式都满足下面的性质:1.表达式只可能包含一个变量‘a’.2.表达式中出现的数都是正整数,而且都小于10000.3.

NOIP2005 等价表达式

做题记录: 2016-08-10 23:35:09 背景 NOIP2005 提高组 第四道 描述 明明进了中学之后,学到了代数表达式.有一天,他碰到一个很麻烦的选择题.这个题目的题干中首先给出了一个代数表达式,然后列出了若干选项,每个选项也是一个代数表达式,题目的要求是判断选项中哪些代数表达式是和题干中的表达式等价的. 这个题目手算很麻烦,因为明明对计算机编程很感兴趣,所以他想是不是可以用计算机来解决这个问题.假设你是明明,能完成这个任务吗? 这个选择题中的每个表达式都满足下面的性质: 1.