orz picks

前置skill

基础求导

(全世界应该只有我不会求导了吧……=。=,但考虑到可能有小学生在看这篇文章,所以还是讲一下吧
导数,是微积分中的重要基础概念,关于它的具体内容就不讲了,在本文中,你只要知道,求导是用来拟合一个函数在各处的斜率的东西,并且有:
若$f(x)=x^{a}$,则$f'(x)=ax^{a-1}$($f'(x)$:一阶导数)。由此可知,还有$f”(x)=a(a-1)x^{a-2}$($f”(x)$:二阶导数)等等。

泰勒展开

将一个函数在$x_0$处泰勒展开可得:
$$f(x)=f(x_0)+\frac{f'(x_0)}{1!}(x-x_0)+\frac{f”(x_0)}{2!}(x-x_0)^2+…+\frac{f^n(x_0)}{n!}(x-x_0)^n$$

多项式求逆

戳这里

多项式牛顿迭代

已知$G(x)$,求解$G(F(x)) \equiv 0 \pmod{x^n}$

假设已经存在$G(H(x)) \equiv 0 \pmod{x^{\frac{n}{2}}}$
我们把$G(F(x))$在$H(x)$处泰勒展开一下。
又因为$G(H(x)) \equiv 0 \pmod{x^{\frac{n}{2}}}$,而$G(F(x)) \equiv 0 \pmod{x^n}$,$G(F(x))$中$F(x)$次数较小的$\frac{n}{2}$项在模$x^n$意义下能够产生的贡献是0,而$G$是一个多项式,所以次数较大的$\frac{n}{2}$项不会影响次数较小的这些项,因此$F(x)$的前$\frac{n}{2}$项就是$H(x)$,则$F(x)-H(x)$的前$\frac{n}{2}$项为0,则$(F(x)-H(x))^2 \pmod{x^n} \equiv 0$。
则有:
$$G(F(x)) \equiv G(H(x))+G'(H(x))(F(x)-H(x)) \equiv 0 \pmod{x^n}$$
也就是:
$$F(x) \equiv H(x)-\frac{G(H(x))}{G'(H(x))} \pmod{x^n}$$
于是我们可以不断缩小$n$的规模,同时利用多项式求逆来搞这些东西了。

多项式开根

即求$F(x)^2 \equiv P(x) \pmod{x^n}$,$P(x)$已知,就是一个常数。
那么我们设$G(A)=A^2-P$,于是我们就可以利用多项式牛顿迭代的式子来求解$F(x)$辣。
很容易知道:
$$F(x)=H(x)-\frac{H(x)^2-P(x)}{2H(x)}$$

例题

codeforces 438E/bzoj3625 小朋友和二叉树
我们设$f(x)$表示权值和为$x$的二叉树形态个数,设$a(x)$表示$c$集合中是否存在权值$x$,则通过枚举根节点权值和根节点两个叉上子树的权值和,可得一个递推式:
$$f(t)=f(x)f(y)a(t-x-y)$$
边界:$f(0)=1$
也就是说,$f(x)=f(x)^2a(x)+1$
解得:$f(x)=\frac{1±\sqrt{1-4a(x)}}{2a(x)}$
分子分母同时乘以$1 ∓ \sqrt{1-4a(x)}$,并舍去分母有可能为0的那个解可得:
$$f(x)=\frac{2}{1+\sqrt{1-4a(x)}}$$
多项式求逆+开根即可完成本题。

#include<bits/stdc++.h>
using namespace std;
#define RI register int
int read() {
    int q=0;char ch=' ';
    while(ch<'0'||ch>'9') ch=getchar();
    while(ch>='0'&&ch<='9') q=q*10+ch-'0',ch=getchar();
    return q;
}
const int mod=998244353,N=262150,G=3;
int n,m,inv2;
int A[N],B[N],C[N],rev[N],c[N],tmp[N],len[N];
int ksm(int x,int y) {
    int re=1;
    for(;y;y>>=1,x=1LL*x*x%mod) if(y&1) re=1LL*re*x%mod;
    return re;
}
void NTT(int *a,int n,int x) {
    for(RI i=0;i<n;++i) if(rev[i]>i) swap(a[i],a[rev[i]]);
    for(RI i=1;i<n;i<<=1) {
        int gn=ksm(G,(mod-1)/(i<<1));
        for(RI j=0;j<n;j+=(i<<1)) {
            int t1,t2,g=1;
            for(RI k=0;k<i;++k,g=1LL*g*gn%mod) {
                t1=a[j+k],t2=1LL*g*a[j+i+k]%mod;
                a[j+k]=(t1+t2)%mod,a[j+i+k]=(t1-t2+mod)%mod;
            }
        }
    }
    if(x==1) return;
    reverse(a+1,a+n);int inv=ksm(n,mod-2);
    for(RI i=0;i<n;++i) a[i]=1LL*a[i]*inv%mod;
}
void getrev(int t)
    {for(RI i=0;i<t;++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<(len[t]-1));}
void getinv(int *a,int *b,int n) {
    if(n==1) {b[0]=ksm(a[0],mod-2);return;}
    getinv(a,b,n>>1);
    int kn=n<<1;getrev(kn);
    for(RI i=0;i<n;++i) c[i]=a[i],c[n+i]=0;
    NTT(c,kn,1),NTT(b,kn,1);
    for(RI i=0;i<kn;++i) b[i]=1LL*b[i]*(2-1LL*c[i]*b[i]%mod+mod)%mod;
    NTT(b,kn,-1);
    for(RI i=n;i<kn;++i) b[i]=0;
}
void getsqrt(int *a,int *b,int n) {
    if(n==1) {b[0]=1;return;}
    getsqrt(a,b,n>>1);int kn=n<<1;
    for(RI i=0;i<n;++i) tmp[i]=0;
    getinv(b,tmp,n),getrev(kn);
    for(RI i=0;i<n;++i) c[i]=a[i],c[n+i]=0;
    NTT(c,kn,1),NTT(b,kn,1),NTT(tmp,kn,1);
    for(RI i=0;i<kn;++i) b[i]=1LL*(b[i]+1LL*c[i]*tmp[i]%mod)%mod*inv2%mod;
    NTT(b,kn,-1);
    for(RI i=n;i<kn;++i) b[i]=0;
}
int main()
{
    n=read(),m=read();
    for(RI i=1;i<=n;++i) A[read()]=1;
    int kn=1;while(kn<=m) kn<<=1,len[kn]=len[kn>>1]+1;
    len[kn<<1]=len[kn]+1;
    for(RI i=0;i<kn;++i) A[i]=(mod-4LL*A[i]%mod)%mod;
    A[0]=1,inv2=ksm(2,mod-2);
    getsqrt(A,B,kn),B[0]=(B[0]+1)%mod;
    getinv(B,C,kn);
    for(RI i=1;i<=m;++i) printf("%d\n",(C[i]+C[i])%mod);
    return 0;
}
分类: 文章

litble

苟...苟活者在淡红的血色中,会依稀看见微茫的希望

发表评论

电子邮件地址不会被公开。 必填项已用*标注

你是机器人吗? =。= *