• 多项式


    多项式求逆

    给定多项式 (F) ,求一个 (G) 使得 (F*Gequiv1 pmod {x^n})

    多项式的模意义是指次数大于等于 (n) 的项都当成 (0),考虑倍增,设有多项式 (A) 满足 (F*Aequiv 1 pmod {x^{lceil{frac{n}2} ceil}}) ,上取整的意思为了让它平方后大于等于(n)的项都当成(0)

    显然有 (F*Gequiv1 pmod {x^{lceil{frac{n}2} ceil}}) ,根据模的定义可知。

    所以有 (F*(G-A)equiv 0 pmod{x^{lceil{frac{n}2} ceil}})(F) 不可能为 (0),于是 ((G-A)^2equiv0 pmod{x^n}),继续推一发,得到 (G^2-2AG+A^2equiv 0 pmod{x^n}),两边同时乘 (F) 得到 (G-2A+A^2Fequiv 0 pmod{x^n}),所以推出 (Gequiv 2A-A^2F),只有常数项的时候求逆元即可,分治即可求出。

    多项式开根

    求一个多项式 (F) 满足 (F^2=G),若 (F) 有两个,一般取正的。

    仍然使用倍增,设 (F^2equiv Gpmod {x^{2n}}),假设已经求出了 (A^2equiv Gpmod {x^n}) ,那么有 (F^2-A^2equiv0 pmod {x^n})

    易得

    [(F+A)(F-A)equiv0 pmod {x^n} ]

    [(F-A)equiv0 pmod {x^n} ]

    [(F-A)^2equiv0 pmod {x^{2n}} ]

    [F^2+A^2-2AFequiv0 pmod {x^{2n}} ]

    [G+A^2-2AFequiv0 pmod {x^{2n}} ]

    [Fequiv frac{G+A^2}{2A}pmod {x^{2n}} ]

    在只有常数项的时候可以直接求出。

    若常数项为 (1)(0) ,开根后较为显然,但是有些毒瘤出题人并不喜欢简单,所以对于模意义下开根就比较重要 。

    此时需要用到二次剩余

    多项式除法

    给定多项式 (F,G),求两个多项式 (A,B) 满足 (F=A*G+B)

    其中 (F,G,A) 的项数分别为 (n,m,n-m),要求 (B) 的项数小于 (m)

    定义一种变换,(F_{R(x)}=x^n F(frac{1}x)),容易发现这种变换就是将(F)的系数reverse了一下。

    [F=A*G+B ]

    [F(frac{1}x)=A(frac{1}x)G(frac{1}x)+B(frac{1}x) ]

    [x^nF(frac{1}x)=x^nA(frac{1}x)G(frac{1}x)+x^nB(frac{1}x) ]

    [x^nF(frac{1}x)=x^{n-m}A(frac{1}x)x^mG(frac{1}x)+x^{n-m+1}x^{m-1}B(frac{1}x) ]

    [F_{R(x)}=A_{R(x)}G_{R(x)}+x^{n-m+1}B_{R(x)} ]

    模一下 (x^{n-m+1}) 就能得到

    [F_{R(x)}equiv A_{R(x)}G_{R(x)} pmod {x^{n-m+1}} ]

    [A_{R(x)}equiv F_{R(x)}G^{-1}_{R(x)} pmod {x^{n-m+1}} ]

    多项式求逆即可。

    多项式求导和积分

    求导,([x^{i-1}]F'=[x^i]F imes i)

    积分,积分是求导的逆运算,对一个多项式积分的结果表示哪个多项式求导得到的是这个多项式

    ([x^i]int F'=frac{[x^{i-1}]F'}i)

    多项式 (ln)

    求一个多项式 (F) 满足 (G=ln F)

    两边求导得到 (G'=ln'F F')

    (ln)的导数可以知道(ln'F=frac{1}F)

    所以 (G'=frac{F'}F)

    于是 (G=intfrac{F'}F)

    多项式exp

    (G(x)equiv e^{f(x)}pmod {x^n},G_1(x)equiv e^{f(x)} pmod {x^{frac{n}2}})

    (Gequiv G_1(1-lnG_1+F) pmod {x^n})

    证明略

    上边的式子虽然易懂但是比较繁琐,因为对于不同的东西需要用到不同的式子,考虑更加通用的办法——牛顿迭代。

    泰勒展开

    对于一个函数 (F)(F(x)) 的值可以近似看作在 (x_0) 处泰勒展开的值,即

    [F(x)=sum_{i=0}^{+infty} frac{F^{(i)}_{x_0}(x-x_0)^i}{i!} ]

    这个式子看上去貌似到正无穷没有办法求,但是由于它递减的很快所以基本上只需要求前几项即可。

    牛顿迭代

    考虑如果求出了 (F(x) equiv 0 pmod {x^{lceilfrac{n}2 ceil}}) 的一个解 (x_0) ,如何求出另一个解 (x) 满足 (F(x) equiv 0 pmod {x^{n}})

    (F(x))(x_0) 处泰勒展开,容易得到

    [F(x)=F_{x_0}+F'_{x_0}(x-x_0)+.... ]

    注意到后边写了省略号,并不是我懒得写了,而是因为没有用了,因为 (x)(x_0) 在模 ({x^n}) 的意义下,前一半项是一样的,所以 (x-x_0) 的最低次项也是 (frac{n}2) 即大于 (2) 的次幂全是 (0)

    于是有

    [F_{x_0}+F'_{x_0}(x-x_0) equiv 0 pmod {x^n} ]

    [F'_{x_0}xequiv F'_{x_0}x_0-F_{x_0} pmod {x^n} ]

    [xequiv x_0-frac{F_{x_0}}{F'_{x_0}} pmod {x^n} ]

    这样推式子就简单的多了,更具体的,只需要构造一个函数 (F(x)equiv0 pmod {x^n}) 即可。

    例如多项式乘法逆,构造函数 (F(x)=frac{1}x-G) ,其中 (G) 为给定的多项式 。

    那么我们要求的实际上就是 (F(x)equiv0 pmod {x^n}) 的一个解。

    直接代牛顿迭代,有

    [xequiv x_0 - frac{frac{1}{x_0}-G}{-frac{1}{x_0^2}} pmod {x^n} ]

    [xequiv 2x_0-Gx_0^2 pmod {x^n} ]

    多项式开根,构造函数(F(x)=x^2-G) ,其中 (G) 为给定多项式。

    代牛顿迭代,得到

    [xequiv x_0-frac{x_0^2-G}{2x_0} pmod {x^n} ]

    [xequiv frac{x_0^2+G}{2x_0} pmod {x^n} ]

    简单易懂

    任意模数多项式乘法

    总有一些毒瘤出题人喜欢把模数搞得奇怪,让你没办法做 (NTT) ,这时候可以用 (CRT) ,但是常数过于大,就不大好玩 。

    考虑一个古老的算法,其实也不是很古老,只是一段时间没怎么用过,(FFT)

    因为 (FFT) 是不用取模的,所以可以直接乘然后最后一起取模,不过模数很大容易炸精,所以要拆系数,不妨令 ([x^i]F=a_0 imes T +b_0) ,然后分别求出(a,b)最后合并即可,即分别求出(a_0a_1,a_0b_1+a_1b_0,b_0b_1),这样做大概需要七次 (FFT) ,还是太慢了。

    于是使用魔法,使得能够快速求出要求的几项。

    (P=a+bi,Q=a-bi),显然他们的系数是共轭的,有一个结论

    (Q_0=P_0),其余的(Q_i=P_{n-i}),即(Q_i=P_{(n-1)&(n-i)}),所以只需要求出 (P),然后就有了 (Q),这样就把两次 (NTT) 合并成了一次 。此时再暴力求出剩下的几项只要五次,考虑继续优化。

    (A=a_0a_1+b_0b_1i,B=a_0b_1+a_1b_0),这样只需要做两次 (IDFT) 即可,所以就可以写出四次的 (MTT) 了。

    多项式快速幂

    给定多项式 (G), 求一个 (F) ,使得 (F=G^k)

    比较好推,(ln F=kln G) ,(F=e^{kln G})

    多项式复合

    给定两个多项式 (F,G) ,求一个多项式(H(x)equiv F(G(x)) pmod {x^n})

    考虑暴力做,依次考虑 (G^i) 的贡献,与 (F) 的系数相乘后加入到答案里边,时间复杂度(O(n^2logn)),常数略大。

    事实上没有必要把他们都乘出来

    [H=sum_{i=0}^{n-1}[x^i]FG^i ]

    [H=sum_{i=0}^{L}sum_{j=0}^{L-1}[x^{iL+j}]FG^{iL+j} ]

    [H=sum_{i=0}^{L}G^{iL}sum_{j=0}^{L-1}[x^{iL+j}]FG^{j} ]

    (L=sqrt n),这样只需要预处理出(G^{iL},G^{i})即可,时间复杂度(O(n^2+nsqrt nlogn)),实际上 (n^2) 的部分常数比较小所以跑的飞快。

    多项式复合逆

    给定多项式 (G),求一个多项式 (F),使得 (G(F(x))=x) 。大概考虑一下这个东西有什么意义,比如有一个函数(H(G(x))=P(x)),那么代入复合逆就能够得到,(H(x)=P(F(x))),只需要多项式复合就能够求出 (H)

    拉格朗日反演

    如果有(F(G(x))=x),即(F,G)互为复合逆,同时一定有(G(F(x))=x),可以称 (G(x)=F^{-1}(x)),(F(x)=G^{-1}(x))

    在这种情况下,有这样的式子:

    [[x^n]F(x)=frac{1}n[x^{n-1}](frac{x}{G(x)})^n ]

    [[x^n]H(F(x))=frac{1}n[x^{n-1}]H'(x)(frac{x}{G(x)})^n ]

    可以 (nlogn) 的求出一项系数。

    考虑

    [F=sum_{i=1}^{n}frac{1}i[x^{i-1}](frac{x}{G(x)})^i ]

    [F=sum_{i=0}^{L}sum_{j=1}^{L}frac{1}{iL+j}[x^{iL+j-1}](frac{x}{G(x)})^{iL+j} ]

    [F=sum_{i=0}^{L}sum_{j=1}^{L}frac{1}{iL+j}[x^{iL+j-1}](frac{x}{G(x)})^{iL}(frac{x}{G(x)})^{j} ]

    (L=sqrt n),然后预处理一下后边的式子,可以 (O(n)) 求出两个多项式乘积的某一项,时间复杂度同上。

    有标号连通图计数

    考虑一个简单无向图的个数,显然是(2^{inom{i}{2}}),设其 (EGF)(F)

    一个无向图是由若干连通图拼在一起的,设连通图的 (EGF)(G),枚举联通块个数,有

    [F=sum_{i=0}^{+infty}frac{G^i}{i!} ]

    除掉阶乘是因为连通块之间没有区别。

    所以(F=e^G)(G=ln F)

    边双连通图计数

    求大小为 (n) 的边双连通图的数量。

    由于边双联通图没有一个固定的点,所以不大好做,考虑将其转化为有根的边双,其实就是加入了一个特殊点方便计数而已。

    容易发现,设无根边双的 (EGF)(P) ,有根边双为 (D),那么 (D_i=iP_i),原因是每个点都成为过根。

    考虑有根边双怎么求,一张有根连通图一定是由若干个边双联通分量构成的,考虑根所在的边双联通分量,除去这个边双联通分量后,原图一定会分为若干个有根联通图,枚举根所在的连通分量的大小和划分成的有根连通图的个数,设有根联通图的 (EGF)(F),有

    [F=sum_{i=1}^{+infty}frac{D_ix^isum_{j=0}^{+infty}frac{F^ji^j}{j!}}{i!} ]

    [frac{F^ji^j}{j!}=frac{(Fi)^j}{j!}=e^{Fi} ]

    所以

    [F=D(xe^F) ]

    (F) 显然比较好求,考虑(D) 怎么求,令(H=xe^F),有(F(x)=D(H(x))),两边同时带入 (H) 的复合逆,有,(F(H^{-1}(x))=D(x))

    所以只需要求出(F(H^{-1})),由拉格朗日反演

    [[x^i]F(H^{-1})=frac{1}i[x^{i-1}]F'(frac{x}{H})^i ]

    代入(H=xe^F),有

    [[x^i]F(H^{-1})=frac{1}i[x^{i-1}]F'e^{-iF} ]

    于是可以 (nlogn) 求出 (D) 的一项。

    多项式多点求值

    给定一个 (n) 次多项式和 (m) 个值,求出 (F(a_1),F(a_2),……F(a_m))

    构造两个多项式(P=prod_{i=1}^{frac{n}2}(x-a_i),Q=prod_{i=frac{n}2+1}^n(x-a_i)),那么如果令(F=P*A+B),对于任意 ([1,frac{n}2]) 中的点,(F(a_i)=B(a_i)),原因是代入后 (P)(0),所以就有了理论上是 (nlogn) 实际上有大常数的多项式取模写法。

    实际上取模的做法貌似已经成了时代的眼泪,我们现在已经有了更快的转置做法。

    考虑一种减法卷积,定义 (c=Mult(a,b))(c_i=sum_{j=0}^{+infty}a_jb_{j-i})

    它有一个性质是,(Mult(Mult(a,b),c)=Mult(a,b*c)),可以利用这个性质进行多点求值。

    (F(a_j)) 展开,得到

    [F(a_j)=sum_{i=0}^{n}[x_i]Fa_j^i ]

    观察发现,如果构造一个多项式 (G_j=sum_{i=0}^{n}a_j^ix^i),那么 $ F(a_j) $ 实际上是 (Mult(F,G_j)) 的常数项,证明很简单,代入即可。

    (G) 是一个 (n) 次的多项式,暴力做的话是 (nmlogn) ,不如直接乘,考虑优化,将 (G) 写成封闭形式,(G_j=frac{1}{1-a_jx}),这样就可以 (O(1)) 的算出每一个 (G_j) 的分母,但是还是没啥用,因为乘起来还是要 (O(nlogn)) ,最后我们要的是每一个 (Mult(F,G_j)) 的常数项,考虑求出 (prod_{j=1}^mG_j),可以用分治乘法和求逆求出,直接令(F=Mult(F,prod_{j=1}^mG_j)),再一次进行分治,如果进去左区间就把右区间的贡献去掉,具体的,设 (T=prod_{j=frac{n}2+1}^{n}frac{1}{G_j}),只需要令 (F=Mult(F,T)),进入右区间时同理,原因是暴力做是对于右区间的每一个 (j),进行 (Mult(Mult(F,frac{1}{G_j}),frac{1}{G_j})),由 (Mult(Mult(a,b),c)=Mult(a,b*c)) 知,可以先对右区间卷积起来一起做减法卷积。

    然后就有了小常数的多点求值。

    多项式快速插值

    给定 (n+1) 个点值,要求一个 (n) 次多项式。

    考虑拉格朗日插值法,有

    [F=sum_{i=0}^ny_iprod_{i!=j}frac{x-x_j}{x_i-x_j} ]

    这个式子为什么是对的,其实很简单,发现带入任意 (x_i) 都成立,然后就没了。

    但是直接做是 (O(n^2)) 的,将其进行简单变形。

    [F=sum_{i=0}^nfrac{y_i}{prod_{i!=j}x_i-x_j}prod_{i!=j}{x-x_j} ]

    考虑带有 (y_i) 的那一项,容易发现只需要求出下边的即可,有点难求于是构造一个多项式 (G=prod_{i=0}^nx-x_i),只需要求出 (frac{G(x)}{x-x_i}),这个东西看起来好求但是实际上不是很好玩,因为分子分母在(x=x_i)的时候都是(0)

    这时候就要用到洛必达法则了。

    众所周知,两个无穷小之比或两个无穷大之比的极限可能存在,也可能不存在。因此,求这类极限时往往需要适当的变形,转化成可利用极限运算法则或重要极限的形式进行计算。洛必达法则便是应用于这类极限计算的通用方法 。

    洛必达法则:对于 (frac{f(x)}{g(x)}),若(limlimits_{x→a}f(x)=0,limlimits_{x→a}g(x)=0),那么(limlimits_{x→a}frac{f(x)}{g(x)}=limlimits_{x→a}frac{f'(x)}{g'(x)})

    也就是说,当 (x=x_i) 时,$frac{G(x)}{x-x_i}=frac{G'(x)}{(x-x_i)'}=G'(x) $

    于是有,

    [F=sum_{i=0}^nfrac{y_i}{G'(x_i)}prod_{i!=j}{x-x_j} ]

    使用多项式多点求值即可求出所有的 (G') ,不妨令 (y_i=frac{y_i}{G'(x_i)})

    那么实际上要求的是

    [F=sum_{i=0}^ny_iprod_{i!=j}{x-x_j} ]

    [F_{l,r}=sum_{i=l}^ry_iprod_{i!=j}{x-x_j} ]

    直接暴力拆开,

    [F_{l,r}=sum_{i=l}^{mid}y_iprod_{i!=j}{x-x_j}+sum_{i=mid+1}^ry_iprod_{i!=j}{x-x_j} ]

    [F_{l,r}=sum_{i=l}^{mid}y_iprod_{i=l,i!=j}^{mid}{x-x_j}prod_{i=mid+1}^nx-x_j+sum_{i=mid+1}^ry_iprod_{i=mid+1,i!=j}^n{x-x_j}prod_{i=l}^{mid}x-x_j ]

    [F_{l,r}=F_{l,mid}prod_{i=mid+1}^nx-x_j+F_{mid+1,r}prod_{i=l}^{mid}x-x_j ]

    自底向上乘即可。

    下降幂多项式乘法

    给定下降幂多项式 (F,G),求 (F*G)

    首先考虑一个下降幂单项式 (x^{underline n}) 的点值 (EGF)

    [sum_{i=n}^{+infty}frac{i^underline n}{i!}x^i ]

    [sum_{i=n}^{+infty}frac{1}{(i-n)!}x^i ]

    [sum_{i=0}^{+infty}frac{1}{i!}x^{i+n} ]

    (e^xx^{n}) ,那么只需要将 (F,G) 乘上 (e^x) 即可转化为点值的 (EGF) ,之后直接用点值相乘即可,注意得到的是点值的 (EGF) 所以相乘的时候要乘上一个阶乘。

    下降幂多项式转普通多项式

    给定一个下降幂多项式,求一个与其相等的普通多项式。

    直接将下降幂转化成点值的形式然后快速插值即可。

    普通多项式转下降幂多项式

    给定一个普通多项式,求一个与其相等的下降幂多项式。

    使用多点求值求出下降幂的点值 (EGF) ,然后乘上 (e^{-x}) 即可。

    int - > long long 0 - > 100
  • 相关阅读:
    《演讲之禅》助你成长为一名合格程序员
    JavaScript中设置元素class的三种方法小结
    数据类型和Json格式
    JavaScript给onclick事件赋值,动态传参数实例辩错
    JSON.parse()和JSON.stringify()使用
    javascript写在<head>和<body>里的区别
    Source Insight 相关
    串口接收字符时,最后一个字符延时发送
    嵌入式编程中调试问题全记录
    新版数采仪开发问题全记录
  • 原文地址:https://www.cnblogs.com/anyixing-fly/p/14360158.html
Copyright © 2020-2023  润新知