专栏文章

题解:P1054 [NOIP 2005 提高组] 等价表达式

P1054题解参与者 2已保存评论 1

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
1 条
当前快照
1 份
快照标识符
@mipw1fcr
此快照首次捕获于
2025/12/03 18:52
3 个月前
此快照最后确认于
2025/12/03 18:52
3 个月前
查看原文
首先感谢 @shihaocheng110909
与大部分的写法不同,这里采用分治的写法(比栈要好写)。每次分治查找区间内优先级最低的符号,然后分别递归计算这个符号两边的算式即可。由于数据较小,可以直接枚举 aa 的值,然后依次对于每个算式进行判断结果是否相同。
需要注意的是,由于该题是远古题目,所以给定的字符串里可能有不可见字符(比如 \r),还有括号可能不匹配,我们需要对这种情况对于特殊处理。最后,答案的存储可以用 unsigned long long 的自然溢出,用 hash 的原理,比较最终结果即可。
由于 @shihaocheng110909 的代码马蜂优良,所以使用他的代码。他线下同意了我使用他的代码。
CPP
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
string s[30];
bool vis[30];
ull ll,rr;
int n;
ull yx(char ch){
	if(ch=='+'||ch=='-')return 1;
	if(ch=='*')return 2;
	if(ch=='^')return 3;
}
ull num(int l,int r,string ss){
	ull ans=0;
	for(int i=l;i<=r;i++)ans=ans*10+ss[i]-'0';
	return ans;
}
ull solve(int l,int r,string ss){
	ull ps=0,mid=0;
	for(int i=l;i<=r;i++){
		if(ss[i]=='('){ps++;continue;}
		if(ss[i]==')'){ps--;continue;}
		if(!ps&&(ss[i]=='+'||ss[i]=='*'||ss[i]=='-'||ss[i]=='^')){
			if(yx(ss[mid])>=yx(ss[i]))mid=i;
		}
	}
	ull L=l,R=r;
	while(ss[L]!='+'&&ss[L]!='*'&&ss[L]!='-'&&ss[L]!='^'&&ss[L]!='('&&ss[L]!=')'&&(ss[L]<'0'||ss[L]>'9'))L++;
	while(ss[R]!='+'&&ss[R]!='*'&&ss[R]!='-'&&ss[R]!='^'&&ss[R]!='('&&ss[R]!=')'&&(ss[R]<'0'||ss[R]>'9'))R--;
	if(mid==0){
		if(ss[L]=='('&&ss[R]==')')return solve(L+1,R-1,ss);
		return num(L,R,ss);
	}else{
		if(ss[mid]=='+')return solve(L,mid-1,ss)+solve(mid+1,R,ss);
		if(ss[mid]=='-')return solve(L,mid-1,ss)-solve(mid+1,R,ss);
		if(ss[mid]=='*')return solve(L,mid-1,ss)*solve(mid+1,R,ss);
		if(ss[mid]=='^'){
			ull s1=solve(L,mid-1,ss);
			ull s2=solve(mid+1,R,ss);
			ull ans=1;
			while(s2--)ans*=s1;
			return ans;
		}
	}
}
int main(){
	getline(cin,s[0]);
	s[0]='('+s[0]+')';
	for(int i=1;i<s[0].size()-1;i++){
		if(s[0][i]=='(')ll++;
		if(s[0][i]==')')rr++;
	}
	if(ll<rr){
		while(rr>ll){
			s[0]='('+s[0];rr--;
		}
	}
	if(rr<ll){
		while(rr<ll){
			s[0]=s[0]+')';ll--;
		}
	}
	cin>>n;
	for(int j=1;j<=n;j++){
		char ch;cin>>ch;
		getline(cin,s[j]);
		if(ch!='\n')s[j]=ch+s[j];
		s[j]='('+s[j]+')';
		ll=rr=0;
		for(int i=1;i<s[j].size()-1;i++){
			if(s[j][i]=='(')ll++;
			if(s[j][i]==')')rr++;
		}
		if(ll<rr){
			while(rr>ll)s[j]='('+s[j],rr--;
		}
		if(rr<ll){
			while(rr<ll)s[j]=s[j]+')',ll--;
		}
	}
	for(char xx='0';xx<='9';xx++){
		ull fl=123456789987654321;
		for(int k=0;k<=n;k++){
			string t=s[k];
			for(int i=0;i<t.size();i++){
				if(t[i]=='a')t[i]=xx;
			}
			ull ls=solve(0,s[k].size()-1,t);
			if(fl==123456789987654321)fl=ls;
			if(ls!=fl)vis[k]=1;
		}
	}
	for(int i=1;i<=n;i++){
		if(!vis[i])cout<<char(i-1+'A');
	}
	return 0;
}

评论

1 条评论,欢迎与作者交流。

正在加载评论...