题解 P1054 【等价表达式】
EricWay1024 · · 题解
余观此题,未生特殊代值之意,徒有多项式运算之情。所以然者何?变量单一,形式有限,假一数组,以次数顺列系数,则神形兼备,功能俱全。遂写结构,用重载。又用栈,以计算。
说明白点,就是直接拿个结构体,用多项式每项前的系数存成一个数组,来表示多项式,然后通过重载运算符来支持多项式的各种运算。但这里有个问题,就是a的最高次数可能远远超过10。事实上,有一个测试点的数据就有
(a -6)^10^10
所以多项式数组的大小不能只开到11。但这样的话,这个数组岂不是要开的非常大?然而既然可以用代特殊值的方法来做,我以为,算一下目标和结果的“较低”次数也可以管中窥豹略见一斑。即:如果两个多项式在long long。
但严格来说,将系数对大数(如1e9+7)取模是更严谨的做法。这种做法另一个问题就是代码量比较大,可能需要比较长的编码调试时间。这个思路主要优势是比较直观,也容易想到。另外写的这个struct非常实用。print()稍微完善一下,或者不完善,因为也能看懂,这已经可以用来做数学作业啦!
(原题解发布于2018-09-24,2021-02-25更新)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<ctime>
#include<vector>
#include<stack>
#include<string>
#define N 100
using namespace std;
struct poly{
long long p[N+2];
void clear(){
memset(p, 0, sizeof(p));
}
poly operator= (const poly &b){
this->clear();
for (int i=0; i<=N; i++) p[i]=b.p[i];
return *this;
}
poly operator= (const int b){
this->clear();
p[0]=b;
return *this;
}
poly operator+ (const poly &b) const{
poly c;
for (int i=0; i<=N; i++){
c.p[i]=p[i]+b.p[i];
}
return c;
}
poly operator- (const poly &b) const{
poly c;
for (int i=0; i<=N; i++){
c.p[i]=p[i]-b.p[i];
}
return c;
}
poly operator* (const poly &b) const {
poly c;
c.clear();
for (int i=0; i<=N; i++){
for (int j=0; j<=N; j++){
if (i+j>N) continue;
int k=i+j;
c.p[k]+=p[i]*b.p[j];
}
}
return c;
}
poly pow(const poly &b) const {
//b must be an integer.
int t=b.p[0];
poly ans; ans=1;
poly pas; pas=(*this);
while (t){
if (t&1) {ans=ans*pas;}
pas=pas*pas;
t>>=1;
}
return ans;
}
void print(){
for (int i=N; i>=0; i--){
if (p[i]==0) continue;
if (i!=N) cout<<'+';
cout<<p[i]<<"a^"<<i;
}
cout<<endl;
}
bool operator== (const poly&b) const {
for (int i=0; i<=N; i++){
if (p[i]!=b.p[i]) return false;
}
return true;
}
};
stack<poly> s1;
stack<char> s2;
inline int f(char c){
if (c=='^') return 3;
if (c=='*' ) return 2;
if (c=='+' || c=='-') return 1;
else return 0;
}
inline void js(){
poly a, b; char c;
poly ans;
b=s1.top(); s1.pop();
a=s1.top(); s1.pop();
c=s2.top(); s2.pop();
if (c=='+') ans=a+b;
if (c=='-') ans=a-b;
if (c=='*') ans=a*b;
if (c=='^') ans=a.pow(b);
s1.push(ans);
}
const char L[18]="0123456789+-*^a()";
inline bool legal(char c){
for (int i=0; i<17; i++){
if (c==L[i]) return true;
}
return false;
}
inline poly read(){
string s;
getline(cin, s);
int len=s.size();
int judge=0; bool ok=1;
if (s.empty()) ok=0;
for (int i=0; i<len; i++){
if (s[i]=='(') judge++;
if (s[i]==')') judge--;
if (judge<0) ok=0;
}
if (judge>0) ok=0;
if (!ok) {poly wrong; wrong.clear(); wrong.p[N+1]=1; return wrong;}
//gets(s);
bool flag=0; int temp=0; poly pt;
poly a; a.clear(); a.p[1]=1;
for (int i=0; i<len; i++){
char &n=s[i];
if (!legal(n)) continue;
if (n=='a') {s1.push(a); continue;}
if (n>='0' && n<='9') {temp=(temp<<1)+(temp<<3)+n-'0'; flag=1; continue;}
if (flag) {pt=temp; s1.push(pt); temp=0; flag=0;}
if (n=='(') {s2.push(n); continue;}
if (n==')') {
while (s2.top()!='(') js();
s2.pop();
continue;
}
while (!s2.empty() && f(s2.top())>=f(n)) js();
s2.push(n);
}
if (flag) {pt=temp; s1.push(pt);}
while (!s2.empty()) js();
poly res=s1.top();
s1.pop();
return res;
//s1.top().print();
}
int main(){
poly aim; aim=read();
//aim.print();
int n; scanf("%d\n", &n);
for (int i=0; i<n; i++){
poly now=read();
//now.print();
if (now==aim) {char c='A'+i; cout<<c;}
}
cout<<endl;
return 0;
}