P7088 题解
stardust_Ray · · 题解
首先考虑如何存储向量。关注到向量与向量之间的操作是每一维分开的,所以我们存储一个多项式表示每一维上经过操作后与
对于折叠操作,我们预处理每一个幂次
用多项式存储看起来很错,因为正常情况下会被卡到
时间复杂度
代码细节较多,主要在于:
- 取负这一操作要与减法操作区分开来。
- 对于单目运算符计算之前要把取负都先算掉。
Code:
#include<bits/stdc++.h>
#define For(i,j,k) for(int i=(j);i<=(k);++i)
#define ForDown(i,j,k) for(int i=(j);i>=(k);--i)
#define Debug(fmt, args...) fprintf(stderr,"(function %s, line #%d): " fmt,__func__,__LINE__,##args),fflush(stderr)
#define debug(fmt, args...) fprintf(stderr,fmt,##args),fflush(stderr)
#define within :
#define LJY main
using namespace std;
typedef long long ll;
const int N=1e5+5,mod=1e9;
mt19937 rnd(chrono::system_clock::now().time_since_epoch().count());
inline int read(){
char ch=getchar();int x=0,f=1;
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')
x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return x*f;
}
// -----------------template-------------------
int n;ll a[N],p[N],sum[11];
char s[N];int m;
struct Poly{
ll a[11];
Poly(){For(i,0,10) a[i]=0;}
Poly(int x){For(i,1,10) a[i]=0;a[0]=x;}
ll& operator[](int x){return a[x];}
ll sum(){ll res=0;For(i,0,10) res=(res+a[i]*::sum[i])%mod;return res;} // 计算折叠的答案
};
int add(int x,int y){x+=y;if(x>=mod) return x-mod;else return x;}
int suc(int x,int y){x-=y;if(x<0) return x+mod;else return x;}
Poly operator+(Poly a,Poly b){For(i,0,10) a[i]=add(a[i],b[i]);return a;}
Poly operator-(Poly a,Poly b){For(i,0,10) a[i]=suc(a[i],b[i]);return a;}
Poly operator*(Poly a,Poly b){Poly c;For(i,0,10) For(j,0,10-i) c[i+j]=(c[i+j]+a[i]*b[j])%mod;return c;}
//---------------少项式-------------------
stack<Poly>val;
stack<char>op;
void flatMinus(){ // 每次运算前把取负给做掉
while(!op.empty()&&op.top()=='-'){
auto p=val.top();val.pop();
val.emplace(Poly()-p);op.pop();
}
}
void getCalc(){ // 计算 val 的前两项和 op 中的第一项运算后的结果
char t=op.top();op.pop();
Poly x=val.top();val.pop();
Poly y=val.top();val.pop();
if(t=='+') x=x+y;
else if(t=='-') x=x-y;
else if(t=='*') x=x*y;
else assert(0);
val.emplace(x);
}
void emplace_op(char x){flatMinus();op.emplace(x);}
void emplace_val(Poly x){
val.emplace(x);
if(!op.empty()&&op.top()!=')') getCalc();
}
signed LJY(){
n=read();For(i,1,n) a[i]=read();
For(i,1,n) p[i]=1;sum[0]=n;
For(i,1,10){
For(j,1,n) p[j]=p[j]*a[j]%mod;
For(j,1,n) sum[i]=add(sum[i],p[j]); // 预处理幂次和
}scanf("%s",s+1);m=strlen(s+1);
Poly X;X[1]=1;op.emplace(')');
ForDown(i,m,1){
if(s[i]=='X') emplace_val(X);
else if(s[i]=='N') emplace_val(n);
else if(isdigit(s[i])){
ll sp=0,pw=1;int j=i;
while(j&&isdigit(s[j])){
sp=sp+pw*(s[j]-'0');
j--;pw=pw*10%mod;
}emplace_val(sp);i=j+1;
}
else if(s[i]=='/'){
flatMinus();Poly x=val.top();val.pop();
emplace_val(x.sum());i--;
}else if(s[i]==':'){
flatMinus();
Poly x=val.top();val.pop();
emplace_val(x*x);i--;
}else if(s[i]==')') op.emplace(')');
else if(s[i]=='('){ // 去掉一层括号
flatMinus(),op.pop();
if(!op.empty()&&op.top()!=')') getCalc();
}
else emplace_op(s[i]);
}flatMinus();printf("%d\n",val.top()[0]);
return 0;
}