题意
给你好多表达式,求多少个和第一个等价。
题解
因为题目限制,只有一个变量 a a a,并且次数最高为10次,所以可以大胆猜想两个本质不同的表达式代入某个 a a a时值相同的情况非常的少(具体多少并不知道)。
所以随机random一些数,做表达式求值。
表达式求值坑非常多,主要是空格和括号的问题,打在注释里了。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<string>
#include<cmath>
#include<ctime>
#define ll long long
using namespace std;
const int inf = 1e9+7;
const int mod = 1e9+7;
const int LIM = 1000;
const int N = 30;
const int L = 100;
int n, tot;
string s[N];
int pri[N][L];
bool b[N];
int getPri(char c)
{
if (c == '+' || c== '-') return 1;
else if (c == '*') return 2;
else if (c == '^') return 3;
}
void Initialize(int id)
{
// 空格的锅
// string.erase()传入参数最好放指针
// 第一次错在string的erase,在while循环里也需要判断 i < s.size()
// 不然当 i 指向s.end()的时候鬼知道他删掉了什么
for (int i = 0; i < s[id].size(); i++)
while (i < s[id].size() && (s[id][i] < '0' || s[id][i] > '9') && s[id][i] != '+' && s[id][i] != '-' && s[id][i] != '*' && s[id][i] != '^' && s[id][i] != 'a' && s[id][i] != '(' && s[id][i] != ')')
s[id].erase(s[id].begin()+i);
int now = 0;
for (int i = 0, sz = (int)s[id].size(); i < sz; i++){
if ((s[id][i] >= '0' && s[id][i] <= '9') || s[id][i] == 'a')
pri[id][i] = inf;
else if (s[id][i] == '(')
now += 4, pri[id][i] = inf;
else if (s[id][i] == ')')
now -= 4, pri[id][i] = inf;
else
pri[id][i] = now+getPri(s[id][i]);
}
}
int Pow(int x, int y)
{
int ret = 1;
while (y){
if (y&1) ret = (ll)ret*x%mod;
x = (ll)x*x%mod;
y >>= 1;
}
return ret;
}
int Calc(int x, int y, char c)
{
if (c == '+') return ((ll)x+y)%mod;
else if (c == '-') return ((ll)x-y+mod)%mod;
else if (c == '*') return (ll)x*y%mod;
else return Pow(x, y);
}
int Solve(int id, int l, int r, int x)
{
int pos = -1, minpri = inf;
// 相同优先级的运算符从前往后做,即优先级最高的符号中位置最后的最后做,所以从后往前扫
for (int i = r; i >= l; i--)
if (pri[id][i] < minpri)
minpri = pri[id][i], pos = i;
if (pos == -1){
// 在这里括号要去掉,但是之前的递归不用管括号,因为他的优先级被设置成inf,并不会被当成运算符
while (s[id][l] == '(') l++;
while (s[id][r] == ')') r--;
if (s[id][l] == 'a') return x;
int ret = 0;
for (int i = l; i <= r; i++)
ret = ((ret<<3)+(ret<<1)+s[id][i]-'0')%mod;
return ret;
}
return Calc(Solve(id, l, pos-1, x), Solve(id, pos+1, r, x), s[id][pos]);
}
/*
void test() // test函数对调试非常的有用
{
while (getline(cin, s[0])){
Initialize(0);
cout << Solve(0, 0, s[0].size()-1, 6) << endl;
}
}
*/
int main()
{
// test();
srand((unsigned)time(0));
getline(cin, s[0]); Initialize(0);
cin >> n; getline(cin, s[1]);
for (int i = 1; i <= n; i++)
getline(cin, s[i]), Initialize(i);
memset(b, 0, sizeof(b));
tot = 0;
while (tot <= LIM){
int num = rand()%mod;
int resa = Solve(0, 0, s[0].size()-1, num);
bool fl = 1;
for (int i = 1; i <= n; i++)
if (!b[i] && Solve(i, 0, s[i].size()-1, num) != resa){
fl = 0;
b[i] = 1;
}
if (!fl) tot = 0;
else tot++;
}
for (int i = 1; i <= n; i++)
if (!b[i])
cout << (char)(i+'A'-1);
return 0;
}