P1054 等价表达式
思路:特殊值法
假设a为某个值。将a带入题干式中得出一个值jizhun,并将a的值代入每一个选项式中得到一个值ans。
若ans=jizhun,则该选项式式等价于题干式。 这样做的出错几率极低(尤其是当a的代入值较大时)。
Code:
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int MAXN=105;
const long long MOD=1000000007,uni=100000007;
//注意uni的值(即a)不要取得过大(否则会爆long long)
int n,first[MAXN];
int len;
char ss[MAXN];
int totc;
char charac[MAXN];
int cnt;
char last[MAXN];
int num,now,totl;
long long shu[MAXN],lnum[MAXN],jizhun,ans;
bool book[MAXN];
void read()//手动读字符串
{
char ch=getchar();
while(1)
{
if(ch=='\n')//过滤掉回车
{
return;
}
if(ch==' ') ch=getchar();//过滤掉空格
if(ch!=' ')
{
ss[++len]=ch;
ch=getchar();
}
}
}
void clean()//注意随时清空
{
for(int i=1;i<=num;i++) shu[i]=0;
totc=0,totl=0,cnt=0,num=0,ans=0,now=0,len=0,lnum[1]=0;
}
int find(int x)//将中缀表达式中的多位数的字符串形式转为数。
{
num++;
int tmp=0;
while('0'<=ss[x]&&ss[x]<='9')
{
shu[num]=((shu[num]*10)%MOD+(ss[x]-'0')+MOD)%MOD;
x++,tmp++;
}
return tmp;
}
void query()//后缀表达式求式子的值
{
for(int i=1;i<=cnt;i++)
{
if(last[i]=='0') lnum[++totl]=shu[++now];
if(last[i]=='a') lnum[++totl]=uni;
if(last[i]!='0'&&last[i]!='a')
{
if(last[i]=='+') lnum[totl-1]=(lnum[totl-1]+lnum[totl]+MOD)%MOD;
if(last[i]=='-') lnum[totl-1]=(lnum[totl-1]-lnum[totl]+MOD)%MOD;
//注意减号的模运算法则是(a-b)%MOD=((a%MOD)-(b%MOD)+MOD)%MOD;
if(last[i]=='*') lnum[totl-1]=(lnum[totl-1]*lnum[totl]+MOD)%MOD;
if(last[i]=='^')
{
long long tmp=lnum[totl-1];
for(int j=1;j<=lnum[totl]-1;j++) lnum[totl-1]=(lnum[totl-1]*tmp)%MOD;
}
totl--;
}
}
ans=lnum[1];
}
void work()//中缀转后缀
{
clean();
read();
int i=1;
while(i<=len)
{
if(ss[i]=='a') last[++cnt]=ss[i];
if('0'<=ss[i]&&ss[i]<='9')
{
last[++cnt]='0';
i+=find(i);continue;
}
if(ss[i]=='+'||ss[i]=='-'||ss[i]=='*'||ss[i]=='^')
{
while(first[(int)charac[totc]]>=first[(int)ss[i]]&&totc>0&&charac[totc]!='(')
{
last[++cnt]=charac[totc];
totc--;
}
charac[++totc]=ss[i];
}
if(ss[i]=='(') charac[++totc]=ss[i];
if(ss[i]==')')
{
while(charac[totc]!='('&&totc>0)
{
last[++cnt]=charac[totc];
totc--;
}
totc--;
}
i++;
}
for(int i=totc;i>=1;i--) last[++cnt]=charac[i];
}
int main()
{
first[(int)'(']=3,first[(int)')']=3,first[(int)'^']=3;
first[(int)'*']=2,first[(int)'+']=1,first[(int)'-']=1;
work();query();
jizhun=ans;
scanf("%d",&n);
//注意:这个n读入后会随之来一个'\n',实际读时会把当成一个字符串,然后它的ans会调用文本串的lnum[1]
n+=1;//注意:这个n读入后会随之来一个'\n',实际读时会把当成一个字符串,所以总的字符串读入个数为n+1.
for(int i=1;i<=n;i++)
{
work();query();
if(ans==jizhun) book[i]=1;
}
for(int i=1;i<=n;i++)
if(book[i]==1) cout<<(char)(64+i-1);//n读入后的'\n'实际读时会把当成一个字符串,所以判掉。
return 0;
}