• 多项式应用


    常系数齐次线性递推

    求一个(k)阶齐次线性递推数列(a)的第(n)项。

    给定这个数列的前(k)(a_0,a_1,cdots,a_n),和递推系数(f_1,f_2,cdots,f_k)

    表示

    [a_n=sumlimits_{i=1}^{k}f_i imes a_{n-i} ]

    矩阵优化

    矩阵快速幂不能通过,但是是重要的思想

    设转移矩阵为(A),假设我们构造出序列(c),使得

    [A^n=sumlimits_{i=0}^{k-1}c_iA^i ]

    两边同时乘上初始行向量(a),注意到矩阵乘法的分配律

    [acdot A^n=sumlimits_{i=0}^{k-1}c_icdot acdot A^i ]

    因为我们最终只需要求行向量的第(0)

    [ans=(acdot A^n)_0=sumlimits_{i=0}^{k-1}c_icdot (acdot A^i)0 ]

    注意到等式右边,(a)是初始序列,(A^i)(i)次转移的矩阵,那么((acdot A^i))就是(i)次转移之后的向量,((acdot A^i)_0)就是(i)次转移之后的第(0)个,即原序列的第(i​)

    那么

    [ans=sumlimits_{i=0}^{k=1}a_ic_i ]

    多项式科技

    问题转化为求(c_i),满足(A^n=sumlimits_{i=0}^{k-1}c_iA^i),右边是一个关于(A)的多项式

    因为(sumlimits_{i=0}^{k-1}c_iA^i)的次数较小,考虑它是(A^n mod)另一个关于矩阵的多项式(G(A))之后的余项

    (A^n)换一种形式

    [A^n=Q(A)G(A)+sumlimits_{i=0}^{k-1}c_iA^i ]

    (G(A))满足(G(A)=0),即

    [sumlimits_{i=0}^kg_iA^i=0 ]

    (A)视为一个数(x),问题再一次转化,成为求(G),然后快速幂对(G)取模,即可得到一个关于(A)的多项式(R(A)=sumlimits_{i=0}^{k-1}c_iA^i)

    有结论

    [g_{k-i}=-a_i,g_k=1 ]

    然后多项式取模即可

    scan(n);scan(k);
    init_poly(k+k-1);
    for(int i=1;i<=k;++i){
    	scan(f[i]);f[i]=dec(f[i]%mod,0);
    	R[k-i]=mod-f[i];
    }
    R[k]=1;
    INVG=R;INVG.rev();INVG=Basic::poly_inv(INVG,k+1);
    for(int i=0;i<k;++i){
    	scan(a[i]);a[i]=dec(a[i]%mod,0);
    }
    B[1]=1;F[0]=1;
    for(;n;n>>=1,B=(B*B)%R)if(n&1)F=(F*B)%R;
    int ans=0;for(int i=0;i<k;++i)Add(ans,1ll*F[i]*a[i]%mod);
    printf("%d",ans);
    

    多项式多点求值

    给定多项式(f(x)),以及(m)个数(a_i),表示(m)次询问(f(a_i))的值

    多项式科技

    同上面的思路,将(F(x))表示成(F(x)=Q(x)G(x)+R(x))的形式。构造一个(G(x_0)),使得(G(x_0)=0),那么就有(F(x_0)=R(x_0))

    就再一次变成了多项式取模,最后答案即为(F)取模后的常数项(因为只剩这一项了)

    (G(x))的构造也很好想:(G(x)=x-x_0)

    但是每次都直接取模时间无法承受

    线段树分治

    (F(x))分别对(prodlimits_{i=l}^{mid}(x-x_i))(prodlimits_{i=mid+1}^{r}(x-x_i))取模,两边递归分治即可

    显然这个就是线段树分治的形式

    poly tr[N];
    #define lid (id<<1)
    #define rid (id<<1|1)
    #define mid ((l+r)>>1)
    void build(int id,int l,int r){
    	if(l==r){tr[id][0]=mod-a[l];tr[id][1]=1;return;}
    	build(lid,l,mid);build(rid,mid+1,r);
    	tr[id]=tr[lid]*tr[rid];
    }
    int ans[N];
    void work(int id,int l,int r,poly f){
    	f=f%tr[id];if(l==r){ans[l]=f[0];return;}
    	work(lid,l,mid,f);
    	work(rid,mid+1,r,f);
    }
    int main(){
    	scan(n);++n;scan(m);F.Read(n);
    	init_poly(max(n<<1,m<<1)+5);
    	for(int i=1;i<=m;++i)scan(a[i]);
    	build(1,1,m);
    	work(1,1,m,F);
    	for(int i=1;i<=m;++i)putint(ans[i],'
    ');
    }
    
  • 相关阅读:
    李超线段树 [Heoi2013]Segment
    [置顶] 九月半集训总结
    [置顶] 我想学学
    图论+前缀和 任(duty)
    模拟 飞(fly)
    入坑 可持久化线段树——主席树
    一次爆炸的联考
    HASH+平衡树 [JSOI2008]火星人prefix
    乱搞+STL平衡树 序列
    数学+图论 建造游乐场
  • 原文地址:https://www.cnblogs.com/harryzhr/p/14736759.html
Copyright © 2020-2023  润新知