题解 P5050 【模板】多项式多点求值
整了一天,没救了(
使用了非(多次)取模做法,但是一个点跑 1.2s,难过。
理论推导
约定
由余式定理有
设
由于
多项式取模告诉我们
设
可以发现有
又因为
注意此处的后
于是复杂度为
具体实现
仅供参考。
首先预处理一下每个分治段的
以便处理,我们钦定
举个例子,分治到左区间时:
那我们大概需要将第一层分治的
搞清楚这个,大概就可以实现了。
其他两篇题解的代码是真的没看懂,不知道为啥要翻转
Code
给点核心代码。
因为
此处将 m 补齐至二的次幂,同时满足
EVA->新世纪福音战士
void eva_solve(ull *F,int l,int r,int dep,int id){
static ull H[maxn],A[maxn],B[maxn],x,y;
if(l==r) return;
int len=r-l+1;
int lim=len<<1;
int mid=(l+r)>>1;
memcpy(H,EVA[dep]+l,8*len);
memcpy(A+1,EVA[dep+1]+l,4*len),A[0]=1;
memcpy(B+1,EVA[dep+1]+mid+1,4*len),B[0]=1;
NTT(H,1,lim,id),NTT(A,1,lim,id),NTT(B,1,lim,id);
for(int i=0;i<lim;++i){
x=A[i],y=B[i];
A[i]=H[i]*y%p[id];
B[i]=H[i]*x%p[id];
}
NTT(A,-1,lim,id),NTT(B,-1,lim,id);
memcpy(EVA[dep+1]+l,A+(len>>1),4*len);//后len>>1个
memcpy(EVA[dep+1]+mid+1,B+(len>>1),4*len);
memset(H,0,8*lim),memset(A,0,8*lim),memset(B,0,8*lim);
eva_solve(F,l,mid,dep+1,id);
eva_solve(F,mid+1,r,dep+1,id);
}
void eva_init(ull *X,int l,int r,int dep,int id){
static ull A[maxn],B[maxn];
if(l==r){
EVA[dep][l]=X[l]>0?p[id]-X[l]:-X[l];
return;
}
int len=r-l+1;
int mid=(l+r)>>1;
eva_init(X,l,mid,dep+1,id);
eva_init(X,mid+1,r,dep+1,id);
int lim=len<<1;
memcpy(A+1,EVA[dep+1]+l,4*len),A[0]=1;
memcpy(B+1,EVA[dep+1]+mid+1,4*len),B[0]=1;
NTT(A,1,lim,id),NTT(B,1,lim,id);
for(int i=0;i<lim;++i)
A[i]=A[i]*B[i]%p[id];
NTT(A,-1,lim,id);
memcpy(EVA[dep]+l,A+1,8*len);
memset(A,0,8*lim);
memset(B,0,8*lim);
}
void eva(ull *F,ull *G,ull *X,int len,int id){//X即xi
static ull H[maxn],T[maxn];
int lim=len<<1;
eva_init(X,0,len-1,0,id);
memcpy(H+1,EVA[0],8*len),H[0]=1;
invf(H,T,len+1,id);
memcpy(H,F,8*len),H[len]=0;
reverse(H,H+len);
NTT(H,1,lim,id),NTT(T,1,lim,id);
for(int i=0;i<lim;++i)
H[i]=H[i]*T[i]%p[id];
NTT(H,-1,lim,id);
memcpy(EVA[0]+1,H,8*(len-1)),EVA[0][0]=0;//右移一位
eva_solve(F,0,len-1,0,id);
for(int i=0;i<len;++i)
G[i]=add(F[0],EVA[to[len]][i]*X[i]%p[id],p[id]);
memset(T,0,8*(len+1));
memset(H,0,8*len);
}