p 0等价的c语言表达式是什么,洛谷 P1054 等价表达式 解题报告

本文介绍了一道编程题目,涉及中缀表达式的等价判断。通过将中缀表达式转化为后缀表达式,并利用栈进行运算,实现表达式的等价性检查。算法实现过程中需要注意括号、运算符优先级和幂次运算的处理。文章还提到在处理大整数时使用模运算避免溢出,以及如何选取测试用例确保算法的正确性。
摘要由CSDN通过智能技术生成

P1054 等价表达式

题目描述

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

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

这个选择题中的每个表达式都满足下面的性质:

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……

输入输出格式

输入格式:

输入文件的第一行给出的是题干中的表达式。

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

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

输出格式:

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

写完这道题我真想吐血十升。。。

写完这道题我真想吐血十升。。。

写完这道题我真想吐血十升。。。

两个点:

完美算法不好写,提供一些质数作为a的值代入计算即可

中缀表达式转后(前)缀表达式。

中缀表达式转后缀表达式

栈s1存数字或运算符,s2存运算符

从左至右扫描

数字进s1

运算符讨论

若s2栈顶优先级小于进来的,我们认为是合法的(想想为什么等于不行)

否则弹出s2到s1直到合法

括号要多一些判断

非完美算法的细节:

为了避免爆ll,要mod一个大质数。

质数不能太大,不然依旧会爆 也不能太小,不然负数模会出问题 (幸运数字1000000007) 不能每一步都膜,会很慢

a的取值要小,否则很可能要出问题

a的数量不能多不能少,否则很可能会出问题

总结:非完美算法要在看脸的基础上,多想想

code:

// luogu-judger-enable-o2

#include

#include

#include

#define ll long long

using namespace std;

int n;

ll last[15],now[15];

int is[260];

ll pre[5]={5,7,11,2,3};

ll mod=1000000007;

char C[60];

void init()

{

for(int i='0';i<='9';i++)

is[i]=1;

is[int('(')]=2;

is[int('+')]=3;

is[int('-')]=3;

is[int('*')]=4;

is[int('^')]=5;

is[int(')')]=6;

is[int('a')]=7;

}

int cnt;

void read()

{

char c=getchar();

while(!is[c]) c=getchar();

cnt=-1;

while(c!='\r')

{

if(is[c])

C[++cnt]=c;

c=getchar();

}

}

struct node

{

int k;//符号1还是数字0

ll c;//数学或者AS码

node(){}

node(int k,ll c)

{

this->k=k;

this->c=c;

}

};

ll get_pow(ll n1,ll n2)

{

ll nn=1;

while(n2)

{

nn=nn*n1;

if(nn>=mod)

nn%=mod;

n2--;

}

return nn;

}

stack s1,s2;

bool get(char *now,int cnt,int flag)

{

while(!s1.empty()) s1.pop();

while(!s2.empty()) s2.pop();

for(int k=0;k<=4;k++)

{

for(int i=0;i<=cnt;i++)

{

ll x=0;

char c=*(now+i);

if(is[c]==1)

{

while(is[c]==1&&i<=cnt) {x=x*10+c-'0';i++;c=*(now+i);}

node tt(0,x);

s1.push(tt);

i--;

}

else if(is[c]==7)

{

node tt(0,pre[k]);

s1.push(tt);

}

else if(is[c]==6)

{

while(!s2.empty())

{

if(s2.top().k&&is[s2.top().c]==2)

break;

s1.push(s2.top());

s2.pop();

}

if(s2.empty())

return false;

else

s2.pop();

}

else

{

node tt(1,c);

while(!s2.empty()&&is[s2.top().c]>=is[c]&&s2.top().c!='('&&c!='(')

{

s1.push(s2.top());

s2.pop();

}

s2.push(tt);

}

}

while(!s2.empty())

{

if(is[s2.top().c]==2)

return false;

s1.push(s2.top());

s2.pop();

}

while(!s1.empty())

{

s2.push(s1.top());

//printf("%d ",s1.top().c);

s1.pop();

}

//printf("\n");

while(!s2.empty())

{

node tt=s2.top();

s2.pop();

if(tt.k)

{

ll t1=s1.top().c;

s1.pop();

ll t2=s1.top().c;

s1.pop();

ll t3;

if(char(tt.c)=='+')

t3=t1+t2;

else if(char(tt.c)=='-')

t3=t2-t1;

else if(is[tt.c]==4)

{

t3=t2*t1;

if(t3>=mod)

t3%=mod;

}

else if(is[tt.c]==5)

t3=get_pow(t2,t1);

tt.c=t3;

tt.k=0;

s1.push(tt);

}

else

s1.push(tt);

}

int ttt=s1.top().c%mod;

if(flag)

last[k]=s1.top().c%mod;

else if(last[k]!=ttt)

return false;

s1.pop();

}

return true;

}

int main()

{

init();

read();

get(C,cnt,1);

char c=getchar();

n=0;

while(!is[c]) c=getchar();

while(c!='\r') {n=n*10+c-'0';c=getchar();}

for(int i=0;i

{

read();

if(get(C,cnt,0))

printf("%c",char(i+'A'));

}

return 0;

}

2018.4.29

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值