标签:中间 介绍 work main printf cst math 数字 tin
给出一个表达式,求之后给出的与之等价的表达式。
保证每个表达式最多只有一个变量 \(a\),可能有 +,-,*,(,),^
运算。
由于只有一个变量,我们可以将 \(a\) 特殊值化,如果最终结果相同那么判定两式等价。
为了减小误差,我们可以多取几个值,但是由于有乘方操作所以最好不要太大。
之后就是中缀表达式的计算,我采用的方法是中缀转后缀再求值,具体方法下文介绍。
有了这个思路就可以开始实现了。
采用 cin
和 scanf
输入都会有点问题,因为中间可能有对于空格。
所以这里采用 getchar
写一个类似快读函数来输入。
string read(){
string sum;
char c=getchar();
while(c==‘\n‘ || c==‘\r‘) c=getchar();//在 windows 和 Linux 下的换行符分别是 \n 和 \r。
while((c>=‘0‘ && c<=‘9‘) || c==‘a‘ || c==‘+‘ || c==‘-‘ || c==‘*‘ || c==‘/‘ || c==‘^‘ || c==‘(‘ || c==‘)‘ || c==‘ ‘){
if(c!=‘ ‘) sum+=c;
c=getchar();
}
return sum;
}
考虑建立一个符号栈,进行一下操作:
但是这个题目毒瘤还有括号不匹配的情况可能会直接导致 RE,所以需要特判。
为了方便统计数字,防止类似 4+1+2 -> 41+2+
导致 4,1
两个数字变为 41
的情况发生,加上 .
。
stack<char>st;
int n=s.length();
string change(){
string a;
for(int i=0;i<n;i++){
if((s[i]>=‘0‘ && s[i]<=‘9‘) || s[i]==‘a‘) {a+=s[i];continue;}//遇到一个数字或 a 直接输出。
a+=‘.‘;//加点。
if(s[i]==‘(‘) st.push(s[i]);//遇到左括号,入栈。
else if(s[i]==‘)‘){//遇到右括号,不断取出栈顶并输出,直到栈顶为左括号,然后左括号出栈。
while(!st.empty() && st.top()!=‘(‘){
a+=st.top();st.pop();
}
if(st.empty()) return "ppp";//特判。
st.pop();
}//遇到运算法,只要 栈顶符号的优先级不低于新符号,就不断取出栈顶并输出。
else if(s[i]==‘+‘ || s[i]==‘-‘){
while(!st.empty() && (st.top()==‘+‘ || st.top()==‘-‘ || st.top()==‘*‘ || st.top()==‘/‘ || st.top()==‘^‘)){
a+=st.top();st.pop();
}
}
else if(s[i]==‘*‘ || s[i]==‘/‘){
while(!st.empty() && (st.top()==‘*‘ || st.top()==‘/‘ || st.top()==‘^‘)){
a+=st.top();st.pop();
}
}
else if(s[i]==‘^‘){
while(!st.empty() && (st.top()==‘^‘)){
a+=st.top();st.pop();
}
}
if(s[i]!=‘(‘ && s[i]!=‘)‘) st.push(s[i]);
}
a+=‘.‘;//加点。
while(!st.empty()) {a+=st.top();st.pop();}//结束后输出栈中所有剩余符号。
return a;
}
用一个栈模拟即可,不再赘述。
stack<int>sa;
int count(string a,int aa){
int len=a.length(),i=0,sum=0;
bool flag=false;
for(int i=0;i<len;i++){
if(a[i]>=‘0‘ && a[i]<=‘9‘) {sum=sum*10+a[i]-‘0‘;flag=true;}//记录数字。
else if(a[i]==‘.‘) {if(flag) sa.push(sum);sum=0;flag=false;}//加点的妙用。
else if(a[i]==‘a‘) sa.push(aa);//给 a 赋特殊值。
else if(a[i]==‘+‘){
int q=sa.top();sa.pop();
int p=sa.top();sa.pop();
sa.push(p+q);
}
else if(a[i]==‘-‘){
int q=sa.top();sa.pop();
int p=sa.top();sa.pop();
sa.push(p-q);
}
else if(a[i]==‘*‘){
int q=sa.top();sa.pop();
int p=sa.top();sa.pop();
sa.push(p*q);
}
else if(a[i]==‘/‘){
int q=sa.top();sa.pop();
int p=sa.top();sa.pop();
sa.push(p/q);
}
else if(a[i]==‘^‘){
int q=sa.top();sa.pop();
int p=sa.top();sa.pop();
sa.push(Pow(p,q));
}
}
return sa.top();
}
虽然题目中说指数不可能大于 10,但是会有这种情况发生 a^10^10^10
。
所以为了避免溢出,应当采用较小的 a
值并用 long long
进行记录。
前文介绍的很清楚了,其实不需要整块的代码介绍,不过还是扔在这里吧。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<stack>
#define N 6000
#define M 1000
#define int long long
using namespace std;
int n,m;
int ans[M],now[M];
string s;
stack<char>st;
stack<int>sa;
string read(){
string sum;
char c=getchar();
while(c==‘\n‘ || c==‘\r‘) c=getchar();
while((c>=‘0‘ && c<=‘9‘) || c==‘a‘ || c==‘+‘ || c==‘-‘ || c==‘*‘ || c==‘/‘ || c==‘^‘ || c==‘(‘ || c==‘)‘ || c==‘ ‘){
if(c!=‘ ‘) sum+=c;
c=getchar();
}
return sum;
}
string change(){
string a;
for(int i=0;i<n;i++){
if((s[i]>=‘0‘ && s[i]<=‘9‘) || s[i]==‘a‘) {a+=s[i];continue;}
a+=‘.‘;
if(s[i]==‘(‘) st.push(s[i]);
else if(s[i]==‘)‘){
while(!st.empty() && st.top()!=‘(‘){
a+=st.top();st.pop();
}
if(st.empty()) return "ppp";
st.pop();
}
else if(s[i]==‘+‘ || s[i]==‘-‘){
while(!st.empty() && (st.top()==‘+‘ || st.top()==‘-‘ || st.top()==‘*‘ || st.top()==‘/‘ || st.top()==‘^‘)){
a+=st.top();st.pop();
}
}
else if(s[i]==‘*‘ || s[i]==‘/‘){
while(!st.empty() && (st.top()==‘*‘ || st.top()==‘/‘ || st.top()==‘^‘)){
a+=st.top();st.pop();
}
}
else if(s[i]==‘^‘){
while(!st.empty() && (st.top()==‘^‘)){
a+=st.top();st.pop();
}
}
if(s[i]!=‘(‘ && s[i]!=‘)‘) st.push(s[i]);
}
a+=‘.‘;
while(!st.empty()) {a+=st.top();st.pop();}
return a;
}
int Pow(int a,int b){
int sum=1;
while(b){if(b&1) sum*=a;a*=a;b>>=1;}
return sum;
}
int count(string a,int aa){
int len=a.length(),i=0,sum=0;
bool flag=false;
for(int i=0;i<len;i++){
if(a[i]>=‘0‘ && a[i]<=‘9‘) {sum=sum*10+a[i]-‘0‘;flag=true;}
else if(a[i]==‘.‘) {if(flag) sa.push(sum);sum=0;flag=false;}
else if(a[i]==‘a‘) sa.push(aa);
else if(a[i]==‘+‘){
int q=sa.top();sa.pop();
int p=sa.top();sa.pop();
sa.push(p+q);
}
else if(a[i]==‘-‘){
int q=sa.top();sa.pop();
int p=sa.top();sa.pop();
sa.push(p-q);
}
else if(a[i]==‘*‘){
int q=sa.top();sa.pop();
int p=sa.top();sa.pop();
sa.push(p*q);
}
else if(a[i]==‘/‘){
int q=sa.top();sa.pop();
int p=sa.top();sa.pop();
sa.push(p/q);
}
else if(a[i]==‘^‘){
int q=sa.top();sa.pop();
int p=sa.top();sa.pop();
sa.push(Pow(p,q));
}
}
return sa.top();
}
void work(bool flag){
s=read();
n=s.length();
string a=change();
if(a=="ppp") return;
for(int i=1;i<=5;i++){
if(flag) ans[i]=count(a,i);
else now[i]=count(a,i);
}
return;
}
bool cmp(){
for(int i=1;i<=5;i++)
if(now[i]!=ans[i]) return false;
return true;
}
signed main(){
work(1);
scanf("%d",&m);
for(int i=1;i<=m;i++){
work(0);
if(cmp()) printf("%c",‘A‘+i-1);
}
return 0;
}
完结撒?。
标签:中间 介绍 work main printf cst math 数字 tin
原文地址:https://www.cnblogs.com/lpf-666/p/13529052.html