CodeVS 1107 等价表达式【NOIP2005】【模拟

本文介绍了一种用于解析和计算包含多种运算符及变量的数学表达式的算法。该算法能够处理加减乘除和幂运算,并通过栈来管理运算符的优先级,实现了对于输入字符串的有效计算。

…………我觉得吧,这题有毒

讲道理,括号都不能匹配的……拿头求值啊x


嗯反正带几个质数进去直接算一算 卡不掉的

……我还是码力不够233333

#include<bits/stdc++.h>
#define MOD 99999989
#define MAXN 57
using namespace std;	int n;
int checker[4]={233,373,103,701};
int ans[4];
char s[MAXN];

void scan(){
	memset(s,0,sizeof s);
	char read_ch=getchar();
	for(int cnt=0;read_ch!='\n'&&read_ch!=EOF;read_ch=getchar(),++cnt){
		while(read_ch==' ')	read_ch=getchar();
		if(read_ch=='\n'||read_ch==EOF)	break;
		s[cnt]=read_ch;
	}
//	puts(s);
}

int stk_num[MAXN];
char stk_opt[MAXN];
int top_num,top_opt;

void calc(){
	int a,b;
	char opt;
	b=stk_num[top_num--];
	a=stk_num[top_num--];
	opt=stk_opt[top_opt--];
	
//	printf("%d %c %d  \n\n",a,opt,b);
	
	if(opt=='+')	stk_num[++top_num]=(a+b)%MOD;
	if(opt=='-')	stk_num[++top_num]=(a-b+MOD)%MOD;
	if(opt=='*')	stk_num[++top_num]=1ll*a*b%MOD;
	if(opt=='^'){
		if(a==0)	return stk_num[++top_num]=0,void();
		int tmp=1;
		for(;b;--b)
			tmp=1ll*tmp*a%MOD;
		stk_num[++top_num]=tmp;
	}
}

bool not_all_left_bracket(){
	for(int i=1;i<=top_opt;++i)	if(stk_opt[i]!='(')	return 1;
	return 0;
}

int check(int x){
	memset(stk_num,0,sizeof stk_num);
	memset(stk_opt,0,sizeof stk_opt);
	
	int lth=strlen(s);
	top_num=top_opt=0;
	
	stk_opt[++top_opt]='(';
	
	for(int i=0,j=0;i<lth;i=j){
		if(s[i]==')'){
			while(stk_opt[top_opt]!='(')
				calc();
			--top_opt;
			++j;
		}
		else{
			if(isdigit(s[i])){
				int tmp=s[i]-'0';
				for(j=i+1;j<lth&&isdigit(s[j]);++j)
					tmp=tmp*10+s[j]-'0',tmp%=MOD;
				stk_num[++top_num]=tmp;
			}
			else{
				if(s[i]=='a')	stk_num[++top_num]=x,++j;
				else{
					if(s[i]=='+')
						while(top_opt&&(stk_opt[top_opt]=='*'||stk_opt[top_opt]=='^'||stk_opt[top_opt]=='-'))	calc();
					if(s[i]=='-')
						while(top_opt&&(stk_opt[top_opt]=='*'||stk_opt[top_opt]=='^'||stk_opt[top_opt]=='-'))	calc();
					if(s[i]=='*')
						while(top_opt&&stk_opt[top_opt]=='^')	calc();
					if(s[i]=='^')
						while(top_opt&&stk_opt[top_opt]=='^')	calc();
					stk_opt[++top_opt]=s[i],++j;
				}
			}
		}
	}
	while(top_opt&¬_all_left_bracket())	calc();
	return stk_num[top_num];
}

int main(){
	freopen("1.in","r",stdin);
//	freopen("QAQ.out","w",stdout);
	
	scan();
	for(int i=0;i<4;++i)	ans[i]=check(checker[i]);
//	for(int i=0;i<4;++i)	printf("ans [ %d ] = %d\n",i,ans[i]);

	scanf("%d\n",&n);
	
	short flag;
	for(int i=0;i<n;++i){
		scan();
		flag=1;
		for(int j=0;j<4;++j){
//			printf("f [ %d ] = %d\n",j,check(checker[j]));
			if(ans[j]!=check(checker[j])){
				flag=0;
				break;
			}
		}
		if(flag)	putchar('A'+i);
//		puts("");
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值