「学习笔记」基础多项式科技
多项式复合
这东西 \(O(n^2+n\sqrt n\log n)\) 过了 \(20000\)
思路是非常精巧的,令 \(L=\sqrt n\) 考虑每个次幂的对系数的贡献那么得到一个式子
分块预处理 \(G\) 的大块和小块就行了
那么这个算是数据结构维护分段多项式的入门题
多项式复合逆
考虑复合的过程和复合逆的过程是类似的
这个做法的正确性如下
Lagrange反演&扩展Lagrange反演
普通反演看懂了,扩展反演没人写证明
式子如下:
证明并不是 \(trivial\) 的,考虑将 \(G(F(x))=x\) 的式子展开并求导得到
考虑反演本身的式子可以消掉 \(x^n\) 那么保留 \(x^{-1}\) 和常数项来观察
由于多项式函数求导以后 \(x^{-1}\) 的系数总是 \(0\)(导数定义),那么考虑对展开的式子除掉 \(F^n(x)\) 并得到 \(x^{-1}\) 的系数有:
对于左边而言,接着展开两个函数的乘积就可以得到 \(x^{-1}\) 的系数必然为 \(1\)
带入得到原反演式子,证毕
多项式多点求值
设 \(F(x)=G(x)Q(x)+R(x)\),那么对于任意一个 \(x_0\) 都会有
当 \(G(x_0)=0\) 时 \(F(x_0)=R(x_0)\)
那么设 \(P_0(x)=\prod_{i=0}^{n/2} x-x_i,P_1(x)=\prod_{i=n/2+1}^n x-x_i\)
让 \(F(x)\) 不停地对去区间的乘积取模就可以最后剩下常数作为答案
分治乘法作预处理,再 \(dfs\) 一次得到所有答案
这里取模的时候千万注意清空
代码如下:
Code Display
namespace Multi_Evaluation{
vector<int> P[N];
inline void prework(int p,int l,int r){
if(l==r){P[p]={mod-qu[l],1}; return ;}
int mid=(l+r)>>1; prework(p<<1,l,mid); prework(p<<1|1,mid+1,r);
P[p]=Mul(P[p<<1],P[p<<1|1]);
return ;
}
inline void solve(int p,int l,int r,vector<int> f){
if(l==r) return ans.push_back(f[0]),void(); int mid=(l+r)>>1;
solve(p<<1,l,mid,Mod(f,P[p<<1]));
solve(p<<1|1,mid+1,r,Mod(f,P[p<<1|1]));
return ;
}
void solve(){
int n=f.size()-1,m=qu.size();
prework(1,0,m-1);
solve(1,0,m,n>=m?Mod(f,P[1]):f);
return ;
}
}
这样 \(1s\ 6e4\) 都跑不了,可行的优化手段,设
所以 \(F(x_i)=[z^0]Mul(F(z),\frac{1}{1-x_iz})\),还是分治,那么每次传入的变成了:
那么每次递归下去的是时候利用 乘另外半边的乘积并且保留区间长度的项数就可以了
用多项式乘法代替了取模,快了很多
多项式快速插值
根据朴素的 \(Lagrange\) 插值法可以得到一个公式:
但是显然暴力乘开是 \(O(n^2)\) 的,那么考虑分治
设多项式 \(p(l,r)=\prod_{i=l}^r x-x_i,v(l,r)=\sum_{i=l}^r y_i\prod_{j\neq i} \frac{x-x_j}{x_i-x_j}\)
容易发现递推公式 \(v(l,r)=v(l,mid)p(mid+1,r)+v(mid+1,r)p(l,mid)\)
但是瓶颈在于对每个 \(i\) 求这个 \(\frac{1}{\prod_{j\neq i} x_i-x_j}\),设 \(G(x)=\prod x-x_i\),所以前面所求就是 \(\frac{x-x_i}{G(x)}\)
带入 \(x=x_i\) 发现上下同时是 \(0\),所以使用洛必达法则来处理,问题就变成了多点求值
Code Display
namespace Quick_interploration{
poly X,Y,T[N<<2],res;
inline void prework(int p,int l,int r){
if(l==r) return T[p]={mod-X[l],1},void(); int mid=(l+r)>>1;
prework(p<<1,l,mid); prework(p<<1|1,mid+1,r);
T[p]=Mul(T[p<<1],T[p<<1|1]);
return ;
}
inline poly dfs(int p,int l,int r){
if(l==r) return {mul(Y[l],ksm(res[l],mod-2))};
int mid=(l+r)>>1;
return Plus(Mul(dfs(p<<1,l,mid),T[p<<1|1]),Mul(dfs(p<<1|1,mid+1,r),T[p<<1]));
}
inline poly query(poly x,poly y){
X=x; Y=y; int n=x.size()-1; prework(1,1,n);
T[1]=deriv(T[1]); T[1].push_back(0);
res=Multi_Evaluaiton::query(T[1],x);
return dfs(1,1,n);
}
}