「学习笔记」基础多项式科技

多项式复合

这东西 O(n2+nnlogn) 过了 20000

思路是非常精巧的,令 L=n 考虑每个次幂的对系数的贡献那么得到一个式子

i=0LGiLj=0L1GjF[xiL+j]

分块预处理 G 的大块和小块就行了

那么这个算是数据结构维护分段多项式的入门题

多项式复合逆

考虑复合的过程和复合逆的过程是类似的

G(x)=i=0L1iL(xF(x))iLj=0L11j(xF(x))j

这个做法的正确性如下

Lagrange反演&扩展Lagrange反演

普通反演看懂了,扩展反演没人写证明

式子如下:

G(F(x))=x[xn]G(x)=1n[xn1](xF(x))n

证明并不是 trivial 的,考虑将 G(F(x))=x 的式子展开并求导得到

Fi1(x)iaiF(x)=1

考虑反演本身的式子可以消掉 xn 那么保留 x1 和常数项来观察

由于多项式函数求导以后 x1 的系数总是 0(导数定义),那么考虑对展开的式子除掉 Fn(x) 并得到 x1 的系数有:

F1(x)F(x)[x1]=[x1]1Fn(x)

对于左边而言,接着展开两个函数的乘积就可以得到 x1 的系数必然为 1

带入得到原反演式子,证毕

H(F(x))[xn]=1n[x1]H(x)1Gn(x)

多项式多点求值

F(x)=G(x)Q(x)+R(x),那么对于任意一个 x0 都会有

F(x0)=G(x0)Q(x0)+R(x0)

G(x0)=0F(x0)=R(x0)

那么设 P0(x)=i=0n/2xxi,P1(x)=i=n/2+1nxxi

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 都跑不了,可行的优化手段,设

Mul(F(x),G(x))=i(sumjfi+jgj)xi

所以 F(xi)=[z0]Mul(F(z),11xiz),还是分治,那么每次传入的变成了:

Mul(F(z),1(1xiz))

那么每次递归下去的是时候利用 乘另外半边的乘积并且保留区间长度的项数就可以了

用多项式乘法代替了取模,快了很多

多项式快速插值

根据朴素的 Lagrange 插值法可以得到一个公式:

F(x)=i=1nyijixxjxixj

但是显然暴力乘开是 O(n2) 的,那么考虑分治

设多项式 p(l,r)=i=lrxxi,v(l,r)=i=lryijixxjxixj

容易发现递推公式 v(l,r)=v(l,mid)p(mid+1,r)+v(mid+1,r)p(l,mid)

但是瓶颈在于对每个 i 求这个 1jixixj,设 G(x)=xxi,所以前面所求就是 xxiG(x)

带入 x=xi 发现上下同时是 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);
    }
}
posted @   没学完四大礼包不改名  阅读(184)  评论(0编辑  收藏  举报
编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示