题解 P1054 【等价表达式】
题面
现在拥有一些表达式,求出其中与原表达式等价的表达式。
分析
很容易想到暴力拆括号。但是,这个方法有2个麻烦的地方
-
需要实现一个储存因式的结构体并支持多种操作
-
(a-1)^10^10^10^10等表达式会让结构体储存的东西多到爆炸。
所以,我们应该想到另一种方式判断。
可以想到,将一个值代入到表达式中,返回结果和基准一样就判对。
我使用的是后缀表达式计算和多值计算。
同时,注意一个坑:luogu中回车表示为\r\n,应当判断2次。
注意:在本题中有括号不匹配的数据,在计算的时候应该适当在左右添加括号以保证表达式括号匹配。
后缀表达式
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<stack>
using namespace std;
const long long M=1000000007;
struct Node{
bool isnum;
long long num;
char ch;
Node(bool isnum=false,long long num=0,char ch='\0'):isnum(isnum),num(num),ch(ch){}
};
stack<char> pri;
stack<long long> qwq;
char rd[60];
Node hz[30][60];
int ln[30],N;
bool isans[30];
long long powr(int O,int P){
if(P<0) P+=M;
long long ret=1,bas=O;
while(P){
if(P&1) ret=(ret*bas)%M;
bas=(bas*bas)%M;
P>>=1;
}
return ret;
}
int ope(char a){
if(a=='-' || a=='+') return 0;
if(a=='*') return 1;
if(a=='^') return 2;
return -1;
}
void run(int bh){
for(int i=0;rd[i];i++){
if(rd[i]=='a') hz[bh][ln[bh]++]=Node(true,-1,'\0');
else if(rd[i]>='0' && rd[i]<='9'){
long long ret=0;
while(rd[i]>='0' && rd[i]<='9') ret=ret*10+rd[i]-'0',++i;
--i;hz[bh][ln[bh]++]=Node(true,ret,'\0');
}
else if(rd[i]=='(') pri.push('(');
else if(rd[i]==')'){
while(!pri.empty() && pri.top()!='('){
hz[bh][ln[bh]++]=Node(false,0,pri.top());
pri.pop();
}
if(!pri.empty()) pri.pop();
}
else{
while(!pri.empty() && ope(pri.top())>=ope(rd[i])){
hz[bh][ln[bh]++]=Node(false,0,pri.top());
pri.pop();
}
pri.push(rd[i]);
}
}
while(!pri.empty()){
if(pri.top()!='(') hz[bh][ln[bh]++]=Node(false,0,pri.top());
pri.pop();
}
while(!pri.empty()){
hz[bh][ln[bh]++]=Node(false,0,pri.top());
pri.pop();
}
}
void rdl(){
char a;
memset(rd,0,sizeof(rd));
int len=0;
while(scanf("%c",&a) && a!='\n' && a!='\r'){
if(a!=' ') rd[len++]=a;
}
scanf("%c",&a);
}
long long mans(int bh,int A){
for(int i=0;i<ln[bh];i++){
if(hz[bh][i].isnum){
if(hz[bh][i].num==-1LL) qwq.push(1LL*A);
else qwq.push(hz[bh][i].num);
}
else{
long long B=qwq.top();qwq.pop();
long long C=qwq.top();qwq.pop();
if(hz[bh][i].ch=='+') qwq.push((C+B)%M);
if(hz[bh][i].ch=='-') qwq.push((C-B+M)%M);
if(hz[bh][i].ch=='*') qwq.push((C*B)%M);
if(hz[bh][i].ch=='^') qwq.push(powr(C,B));
}
}
long long ret=qwq.top();qwq.pop();
return ret;
}
int main(){
srand(15608*1234+545);
rdl();
run(0);
scanf("%d%*c%*c",&N);
for(int i=1;i<=N;i++){
rdl();
run(i);
}
for(int i=1;i<=10;i++){
int A=rand();
long long ans=mans(0,A);
for(int i=1;i<=N;i++){
if(mans(i,A)!=ans) isans[i]=true;
}
}
for(int i=1;i<=N;i++)
if(!isans[i]) printf("%c",i-1+'A');
}