数学杂烩总结(多项式/形式幂级数+FWT+特征多项式+生成函数+斯特林数+二次剩余+单位根反演+置换群)

数学杂烩总结(多项式/形式幂级数+FWT+特征多项式+生成函数+斯特林数+二次剩余+单位根反演+置换群)

因为不会做目录所以请善用ctrl+F

本来想的是笔记之类的,写着写着就变成了资源整理

一些有的没的的前置

导数

\(f'(x)=\lim\limits_{\triangle x\rightarrow 0}\frac{f(x+\triangle x)-f(x)}{\triangle x}\)

\(\sin x:\cos x\)

\(\cos x:-\sin x\)

\(\ln x:\frac{1}{x}\)

\(e^x:e^x\)

\(x^n:nx^{n-1}\)

\(\log_a^x:\frac{1}{x\ln a}\)

\(a^x:a^x\ln a\)

\([af(x)+bg(x)]'=af'(x)+bg'(x)\)

\([f(x)g(x)]'=f(x)g'(x)+f'(x)g(x)\)

\([\frac{f(x)}{g(x)}]'=\frac{f'(x)}{g(x)}-\frac{f(x)g'(x)}{g^2(x)}\)

\([f(g(x))]'=f'(g(x))\times g'(x)\)

牛顿迭代

\(x_i=x_{i-1}-\frac{f(x_{i-1})}{f'(x_{i-1})}\)

泰勒展开

\(f(x)=\sum\limits_{i=0}^{\infty }\frac{f^{(i)}(x_0)(x-x_0)^i}{i!}\)

麦克劳林展开

\(f(x)=\sum\limits_{i=0}^{\infty}\frac{f^{(i)}(0)}{i!}x^i\) (麦克劳林级数)

是泰勒公式的特殊形式。

几个常见泰勒展开

\(ln(1-x)=\sum\limits_{i}-\frac{x^i}{i}\)
\(e^x=\sum\limits_{i=0}^{\infty}\frac{x^i}{i!}\)
\(sin(x)=\sum\limits_{i=0}^{\infty}(-1)^i\frac{x^{2i+1}}{(2i+1)!}\)
\(cos(x)=\sum\limits_{i=0}^{\infty}(-1)^i\frac{x^{2i}}{(2i)!}\)
\(\frac{1}{(1-x)^n}=\sum\limits_{i=0}^{\infty}\binom{i+n-1}{n-1}x^i\) (可以用生成函数理解)

一个结论:\(e^{ix}=cos(x)+i\times sin(x)\)

拉格朗日插值

\(\sum\limits_{i=1}^{n}y_i\prod\limits_{j!=i}\frac{(x-x_j)}{(x_i-x_j)}\)

多项式操作/形式幂级数

多项式求逆

\(C=B\times (2-AB)\)

(因为太常见我就不推了)

多项式开根

\((B-C)=0\)

\(B^2+C^2+2BC=0\)

\(B^2+A+2BC=0\)

\(C=(A/B+B)/2\)

这里插一个二次剩余的Cipolla算法

要求\(x^2=n\)

随一个\(t\),使得\((t^2-n)^{(p-1)/2}=p-1\)

\(I=t^2-n\)

那么答案就是\((t+\sqrt I)^{(p+1)/2}\)

多项式\(ln\)

\(B=lnA\)

\(B'=\frac{A'}{A}\)

(不用倍增!当然倍增也不会错复杂度也一样)

多项式\(exp\)

\(B=e^A\)

\(lnB=A\)

\(lnB-A=0\)

\(B=B-(lnB-A)\times B=B\times (1-lnB+A)\)

多项式求导

for(i=1;i<len;i++)b[i-1]=a[i]*i;

多项式求积分

for(i=1;i<len;i++)b[i]=a[i-1]*inv[i];

多项式快速幂

\(B(x)=A(x)^n\)

\(lnB(x)=nlnA(x)\)

常数项不为\(1\)需要特殊处理。

https://blog.csdn.net/xyz32768/article/details/82832467

多项式除法

定义\(A_R\)满足\(A_R[i]=A[n-i]\)

\(F(x)=Q(x)G(x)+R(x)\) \((deg(F)=n,deg(G)=m,deg(Q)=n-m,deg(R)=m-1)\)

\(F(\frac{1}{x})=Q(\frac{1}{x})G(\frac{1}{x})+R(\frac{1}{x})\)

同乘\(x^n\),得\(F_R(x)=Q_R(x)G_R(x)+R_R(x)x^{n-m+1}\)

\(F_R(x)=Q_R(x)G_R(x)(mod\ x^{n-m+1})\)

\(Q_R=F_R/G_R\)

多项式取模

\(A\ mod\ B=A-\lfloor \frac{A}{B}\rfloor A\)

多项式多点求值

对于\(F(x)\)\(x_1,x_2,...x_m\)求出\(F(x_1),F(x_2),...,F(x_m)\)

思路就是分治,同时利用多项式取模减少多项式的次数。

先计算\(G_{ls}=\prod\limits_{i=l}^{mid}(x-x_i),G_{rs}=\prod\limits_{i=mid+1}^r(x-x_i)\)

对于左边的所有\(x_i\),在\(G_{ls}\)下的点值都是\(0\),因此可以把\(F\)变成\(F\ mod\ G_{ls}\),右边同理。

多项式快速插值

\(F(x)=\sum\limits_{i=1}^n\frac{\prod_{j!=i}(x-x_j)}{\prod_{j!=i}(x_i-x_j)}y_i\)

考虑求出\(\prod_{j!=i}(x_i-x_j)\),设\(M(x)=\prod_{i=1}^n(x−x_i)\),那么我们就是要求\(\frac{M(x)}{x-x_i}\)

\(x=x_i\),根据洛必达法则,得这个式子就等于\(M'(x_i)\),可以多点求值求出这个。

\(v_i=\frac{y_i}{\prod_{j!=i}(x_i-x_j)}\),我们要求的就是\(\sum\limits_{i=1}^nv_i\prod_{j!=i}(x-x_j)\)

同样分治即可。

板子:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define mod 998244353
#define N 400050
char buf[100000],*p1,*p2;
#define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
int rd() {
    int x=0; char s=nc();
    while(s<'0') s=nc();
    while(s>='0') x=(((x<<2)+x)<<1)+s-'0',s=nc();
    return x;
}
int inv[N],ntt_w[2][N],mem[N*100],*ptr=mem;
int A[N],B[N],C[N],D[N],E[N],F[N],G[N],inv2=(mod+1)/2;
int qp(int x,int y=mod-2) {
    int re=1;for(;y;y>>=1,x=ll(x)*x%mod)if(y&1)re=ll(re)*x%mod; return re;
}
int INV(int x) {return qp(x,mod-2);}
namespace Cipolla {
    int I;
    struct cp {
        int x,y;
        cp(){}
        cp(int x_,int y_) {x=x_,y=y_;}
        cp operator * (const cp &u) const {
            return cp((ll(x)*u.x+ll(y)*u.y%mod*I)%mod,(ll(x)*u.y+ll(y)*u.x)%mod);
        }
    };
    bool check(int x) {return qp(x,(mod-1)/2)==1;}
    int Sqrt(int n) {
        srand(123123); rand();
        int t=rand()%mod;while(check((ll(t)*t-n)%mod))t=rand()%mod;
        I=((ll(t)*t-n)%mod+mod)%mod;
        cp re=cp(1,0),x=cp(t,1); int y=(mod+1)/2;
        for(;y;y>>=1,x=x*x)if(y&1)re=re*x;
        re.x=(re.x+mod)%mod;
        return min(re.x,mod-re.x);
    }
}
using namespace Cipolla;
void ntt_init(int l) {
    int j,k,t,w,wn,i;
    for(k=2;k<=l;k<<=1) {t=k>>1;
        wn=qp(3,(mod-1)/k); w=1;
        for(j=0;j<t;j++) ntt_w[0][t+j]=w,w=ll(w)*wn%mod;
        wn=INV(wn); w=1;
        for(j=0;j<t;j++) ntt_w[1][t+j]=w,w=ll(w)*wn%mod;
    }inv[1]=1;for(i=2;i<=l;i++) inv[i]=ll(mod-mod/i)*inv[mod%i]%mod;
}
inline int Md(int x) {return x>=mod?(x-mod):x;}
void ntt(int *a,int len,int flg) {
    int i,j,k,t,tmp,o=flg!=1;
    static ull F[N];
    for(i=0;i<len;i++)F[i]=(a[i]+mod)%mod;
    for(i=k=0;i<len;i++) {
        if(i>k) swap(F[i],F[k]);
        for(j=len>>1;(k^=j)<j;j>>=1);
    }for(k=2;k<=len;k<<=1) {
        t=k>>1;for(i=0;i<len;i+=k) for(j=i;j<i+t;j++) {
            tmp=F[j+t]*ntt_w[o][j-i+t]%mod; F[j+t]=(F[j]+mod-tmp); F[j]=(F[j]+tmp);
        }
    }
    for(i=0;i<len;i++) a[i]=F[i]%mod;
    if(flg==-1)for(tmp=inv[len],i=0;i<len;i++)a[i]=ll(a[i])*tmp%mod;
}
void get_inv(int*,int*,int,int);
void get_root(int*,int*,int,int);
void get_ln(int*,int*,int,int);
void get_exp(int*,int*,int,int);
struct cirno {
    int *a,len;
    cirno(){}
    cirno(int l) {len=l,a=ptr,ptr+=l;}
    void fix(int l) {len=l,a=ptr,ptr+=l;}
    void rev() {reverse(a,a+len);}
    void get_mod(int l) {int i;for(i=l;i<=len;i++) a[i]=0; len=l;}
    cirno operator + (const cirno &u) const {
        cirno re(max(len,u.len)); int i;
        for(i=0;i<re.len;i++) {
            re.a[i]=((i<len?a[i]:0)+(i<u.len?u.a[i]:0))%mod;
        }return re;
    }
    cirno operator - (const cirno &u) const {
        cirno re(len); int i;
        for(i=0;i<len;i++) {
            if(i>=u.len)re.a[i]=a[i];
            else re.a[i]=(a[i]-u.a[i]+mod)%mod;
        }return re;
    }
    cirno operator * (const cirno &u) const {
        cirno re(len+u.len-1);
        int i,j,l=1;
        if(re.len<=200) {
            for(i=0;i<len;i++) if(a[i]) for(j=0;j<u.len;j++) re.a[i+j]=(re.a[i+j]+ll(a[i])*u.a[j])%mod;
            return re;
        }
        while(l<(len+u.len)) l<<=1;
        memset(A,0,l<<2);
        memset(B,0,l<<2);
        memcpy(A,a,len<<2);
        memcpy(B,u.a,u.len<<2);
        ntt(A,l,1),ntt(B,l,1);
        for(i=0;i<l;i++) A[i]=ll(A[i])*B[i]%mod; 
        ntt(A,l,-1);
        memcpy(re.a,A,re.len<<2);
        return re;
    }
    cirno Get_dao() {
        cirno re(len-1); int i;
        for(i=1;i<len;i++) re.a[i-1]=ll(i)*a[i]%mod; return re;
    }
    cirno Get_jifen() {
        cirno re(len+1); int i;
        for(i=1;i<len;i++) re.a[i]=ll(inv[i])*a[i-1]%mod; return re;
    }
    cirno Get_inv(int l) const {
        cirno re(l); get_inv(a,re.a,l,len); return re;
    }
    cirno Get_root(int l) const {
        cirno re(l); get_root(a,re.a,l,len); return re;
    }
    cirno Get_ln(int l) const {
        cirno re(l); get_ln(a,re.a,l,len); return re;
    }
    cirno Get_exp(int l) const {
        cirno re(l); get_exp(a,re.a,l,len); return re;
    }
    cirno Get_pow(int k,int l) const {
        cirno u=Get_ln(l);
        int i;
        for(i=0;i<l;i++) u.a[i]=ll(u.a[i])*k%mod;
        cirno re=u.Get_exp(l);
        return re;
    }
    cirno operator / (cirno u) {
        int n=len,m=u.len,l=1;
        while(l<(n-m+1))l<<=1;
        rev(),u.rev();
        cirno v=u.Get_inv(l);
        v.get_mod(n-m+1);
        cirno re=(*this)*v;
        rev(),u.rev();
        re.get_mod(n-m+1);
        re.rev();
        return re;
    }
    cirno operator % (cirno u) {
        cirno re=*this-u*(*this/u);
        re.get_mod(u.len-1);
        return re;
    }
}tr[N<<2];
char pbuf[2000000],*pp=pbuf;
void write(int x) {
    static int sta[20],tp=0;
    do {sta[++tp]=x%10,x/=10;}while(x);
    while(tp)*pp++=sta[tp--]+'0';
    *pp++=' ';
}
void get_inv(int *a,int *b,int len,int la) {
    if(len==1) {b[0]=qp(a[0]); return ;}
    get_inv(a,b,len>>1,la);
    int l=len<<1,i;
    memset(A,0,l<<2);
    memset(B,0,l<<2);
    memcpy(A,a,min(len,la)<<2);
    memcpy(B,b,len<<2);
    ntt(A,l,1),ntt(B,l,1);
    for(i=0;i<l;i++) A[i]=B[i]*(mod+2-ll(A[i])*B[i]%mod)%mod;
    ntt(A,l,-1);
    memcpy(b,A,len<<2);
}
void get_root(int *a,int *b,int len,int la) {
    if(len==1) {b[0]=Sqrt(a[0]); return ;}
    get_root(a,b,len>>1,la);
    int l=len<<1,i;
    memset(C,0,l<<2);
    memset(D,0,l<<2);
    memset(E,0,l<<2);
    memcpy(C,a,min(len,la)<<2);
    memcpy(D,b,len<<2);
    get_inv(b,E,len,len);
    ntt(C,l,1),ntt(D,l,1),ntt(E,l,1);
    for(i=0;i<l;i++) C[i]=(ll(C[i])*E[i]+D[i])%mod*inv2%mod;
    ntt(C,l,-1);
    memcpy(b,C,len<<2);
}
void get_dao(int *a,int *b,int len) {
    int i; for(i=1;i<len;i++) b[i-1]=ll(i)*a[i]%mod; b[len-1]=0;
}
void get_jifen(int *a,int *b,int len) {
    int i; for(i=1;i<len;i++) b[i]=ll(inv[i])*a[i-1]%mod; b[0]=0;
}
void get_ln(int *a,int *b,int len,int la) {
    int l=len<<1,i;
    memset(F,0,l<<2);
    memset(G,0,l<<2);
    get_dao(a,F,min(len,la));
    get_inv(a,G,len,la);
    ntt(F,l,1),ntt(G,l,1);
    for(i=0;i<l;i++) F[i]=ll(F[i])*G[i]%mod;
    ntt(F,l,-1);
    get_jifen(F,b,len);
}
void get_exp(int *a,int *b,int len,int la) {
    if(len==1) {b[0]=1; return ;}
    get_exp(a,b,len>>1,la);
    int l=len<<1,i;
    memset(C,0,l<<2);
    memset(D,0,l<<2);
    memcpy(C,b,len<<2);
    get_ln(b,D,len,len);
    for(i=0;i<len;i++) D[i]=(i<la?a[i]:0)-D[i];
    D[0]++;
    ntt(C,l,1),ntt(D,l,1);
    for(i=0;i<l;i++) C[i]=ll(C[i])*D[i]%mod;
    ntt(C,l,-1);
    memcpy(b,C,len<<2);
}
#define ls p<<1
#define rs p<<1|1
void build(int l,int r,int p,int *px) {
    if(l==r) {
        tr[p].fix(2);
        tr[p].a[0]=mod-px[l];
        tr[p].a[1]=1;
        return ;
    }
    int mid=(l+r)>>1;
    build(l,mid,ls,px),build(mid+1,r,rs,px);
    tr[p]=tr[ls]*tr[rs];
}
void get_val(cirno F,int l,int r,int p,int *px,int *re) {
    if(F.len<=450) {
        int i,j,t;
        for(i=l;i<=r;i++) {
            ull tmp=0;
            for(j=0,t=1;j<F.len;j++,t=ll(t)*px[i]%mod) {
                tmp=(tmp+ll(t)*F.a[j])%mod;
                if(!(j&7))tmp%=mod;
            }
            re[i]=tmp%mod;
        }return ;
    }
    int mid=(l+r)>>1;
    get_val(F%tr[ls],l,mid,ls,px,re);
    get_val(F%tr[rs],mid+1,r,rs,px,re);
}
cirno solve_polate(int l,int r,int p,int *tmp) {
    if(l==r) {
        cirno re(1); re.a[0]=tmp[l]; return re;
    }
    int mid=(l+r)>>1;
    cirno L=solve_polate(l,mid,ls,tmp);
    cirno R=solve_polate(mid+1,r,rs,tmp);
    return L*tr[rs]+R*tr[ls];
}
void Evaluate(int *px,int *re,cirno F,int m) {
    build(1,m,1,px);
    get_val(F,1,m,1,px,re);
}
cirno Interpolate(int *px,int *py,int n) {
    int i;
    build(1,n,1,px);
    cirno a=tr[1].Get_dao();
    static int t[N];
    get_val(a,1,n,1,px,t);
    for(i=1;i<=n;i++) t[i]=ll(qp(t[i]))*py[i]%mod;
    return solve_polate(1,n,1,t);
}
int main() {
    //LOJ 150
    int n,K,l=1;
    n=rd()+1; K=rd();
    while(l<n)l<<=1;
    ntt_init(l<<1);
    int i;
    cirno a(n);
    for(i=0;i<n;i++) a.a[i]=rd();
    cirno b=a.Get_root(l);
    cirno c=b.Get_inv(l);
    cirno d=c.Get_jifen();
    cirno e=d.Get_exp(l);
    for(i=0;i<l;i++) e.a[i]=-e.a[i];
    for(i=0;i<n;i++) e.a[i]=(e.a[i]+a.a[i])%mod;
    e.a[0]+=2, e.a[0]=(e.a[0]-a.a[0])%mod;
    cirno f=e.Get_ln(l);
    f.a[0]++;
    cirno g=f.Get_pow(K,l);
    cirno ans=g.Get_dao();
    for(i=0;i<n-1;i++) write((ans.a[i]+mod)%mod);
    fwrite(pbuf,1,pp-pbuf,stdout);
    

    //Luogu qiuzhi
    /*int n,m;
    n=rd(),m=rd();
    int i,l=1;
    while(l<=(n+n))l<<=1;
    ntt_init(l);
    cirno a(n+1);
    static int px[N],ans[N];
    for(i=0;i<=n;i++) a.a[i]=rd();
    for(i=1;i<=m;i++) px[i]=rd();
    Evaluate(px,ans,a,m);
    for(i=1;i<=m;i++)printf("%d\n",ans[i]);*/

    //Luogu chazhi
    /*int n,i,l=1;
    n=rd();
    static int px[N],py[N];
    while(l<=(n+n))l<<=1;
    ntt_init(l);
    for(i=1;i<=n;i++)px[i]=rd(),py[i]=rd();
    cirno a=Interpolate(px,py,n);
    for(i=0;i<n;i++)printf("%d ",a.a[i]);*/
}

多项式的复合

\(A(B(x))\)

多项式的复合逆

\(F(x),G(x)\),\(F(G(x))=x\)\(F(x)\)\(G(x)\)互为复合逆。

拉格朗日反演

\(F(x)\)\(G(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\)

特征多项式

https://www.luogu.org/blog/ShadowassIIXVIIIIV/solution-p4723

https://blog.csdn.net/qq_35649707/article/details/78688235

对于懒得推式子选手可以选择记结论:

\(A^n=\sum\limits_{i=0}^{k-1}c_iA^i\)
\(St\times A^n=\sum\limits_{i=0}^{k-1}c_iSt\times A^i\)
\(ans=[0](St\times A^n)=\sum\limits_{i=0}^{k-1}c_i[0](St\times A^i)\)
\(ans=\sum\limits_{i=0}^{k-1}c_iSt_i\)
\(A^n=Q(A)G(A)+\sum\limits_{i=0}^{k-1}c_iA^i\)
\(g_{k-i}=-a_i\)

乘法和取模可以\(O(k^2)\)\(O(k\log k)\)实现。

生成函数

https://www.luogu.org/blog/ShadowassIIXVIIIIV/sheng-cheng-han-shuo-xia-chui

一般生成函数(OGF)

给定一个形如\(x_1+x_2+…+x_m=n\)的方程,求非负整数解的数量,其中\(x_i\)满足:\(x_1\)必须是个偶数\(x_2\)必须是个质数\(x_3\)\(μ\)值不能为\(0\),\(x_4\)必须是一个windy数

指数生成函数(EGF)

给定一些红球、黄球、蓝球和绿球,将其组成一个长度为\(n\)的序列,要求:红球必须有偶数个,白球数量必须是个质数,蓝球数量的\(μ\)值不能为\(0\),绿球数量必须是个windy数

  • 可以看出EGF可以用来解决排列问题。

集合的指数生成函数

给定\(n\)个彼此不同的小球,要求划分为一些集合,每个集合的生成函数是\(F(x)\),求方案数

  • 划分成\(i\)个集合的方案数为\(\frac{F^i(x)}{i!}\),故总方案数为\(\sum\limits_{i=0}^{\infty}\frac{F^i(x)}{i!}=e^{F(x)}\)

一些可以背一背的生成函数

树:\(A(x)=\sum_{n\ge 0}\frac{n^{n-2}}{n!}x^n\)

森林:\(expA(x)\)

无向图:\(C(x)=\sum_{n\ge 0}\frac{2^{\binom{n}{2}}}{n!}x^n\)

无向连通图\(lnC(x)\)

FWT

or卷积和and卷积很好理解

xor卷积看这个https://blog.csdn.net/neither_nor/article/details/60335099

m进制卷积

这个对于or和and还是一个前缀和的性质。

对于xor..可以在模意义下用单位根构造,逆操作可以直接对矩阵求逆。

快速子集变换

大概就是求这么一个式子\(A_i=\sum\limits_{j+k=i,j\&k=0}B_j\times C_k\)

用占位多项式搞一搞即可,多开一维数组存\(1\)的个数,背包合并。

组合数学

第一类斯特林数

\(\begin{bmatrix} n\\ k \end{bmatrix}\) 表示将\(n\)个不同元素分成\(k\)个不同环的方案数,当且仅当两个环不可通过旋转得到时,则两个环不相同。

  1. \(\begin{bmatrix} 0\\ 0 \end{bmatrix}=1,\begin{bmatrix} n\\ k \end{bmatrix}=\begin{bmatrix} n-1\\ k-1 \end{bmatrix}+\begin{bmatrix} n-1\\ k \end{bmatrix}\times (n-1)\) (可能独立成环也可以接到前面某个数的后面。)

  2. \(\sum\limits_{k=0}^n\begin{bmatrix} n\\ k \end{bmatrix}=n!\) (\(\begin{bmatrix} n\\ k \end{bmatrix}\)恰好是\(n\)个元素包含\(k\)个轮换的排列个数)

  3. \(x^{\overline n}=\sum_{k}\begin{bmatrix}n\\ k\end{bmatrix}x^k\) (证明直接带递推式子进去就行,当然也可以用这个式子来定义斯特林数)

  4. \(x^{\underline n}=\sum_{k}\begin{bmatrix}n\\ k\end{bmatrix}(-1)^{n-k}x^k\) (这里的\(\begin{bmatrix}n\\ k\end{bmatrix}(-1)^{n-k}\)其实就是有符号第一类斯特林数了)

求一行第一类斯特林数:

由2式能直接得出一个\(O(n\log n^2)\)的做法,这里说一下\(O(n\log n)\)的做法。

分治,假设我们已经求出来\(x^{\overline n}\),如何求出\(x^{\overline 2n}\)\(x^{\overline {n+1}}\)

对于后者,可以直接\(O(n)\)乘一下,对于前者,相当于要求\(x^{\overline n}\times (x+n)^{\overline n}\)

\(f(x)=\sum\limits_{i=0}^{n}f_ix^i,g(x)=\sum\limits_{i=0}^{n}g_ix_i\),分别是上式左右的生成函数。

\(g(x)=\sum\limits_{i=0}^nf_i(x+n)^i\)

\(g(x)=\sum\limits_{i=0}^nf_i\sum\limits_{j=0}^jx^jn^{i-j}\binom{i}{j}\)

\(g(x)=\sum\limits_{j=0}^n\frac{x^j}{j!}\sum\limits_{i=j}^nf_ii!\frac{n^{i-j}}{(i-j)!}\)

卷积形式,直接\(O(n\log n)\)乘一下。

总的时间复杂度还是\(O(n\log n)\)的。

第二类斯特林数

\(\begin{Bmatrix}n\\ k\end{Bmatrix}\)表示将n个元素分成k个非空集合的方案数,集合内是无序数。

  1. \(\begin{Bmatrix}n\\ k\end{Bmatrix}=\begin{Bmatrix}n-1\\k-1\end{Bmatrix}+k\times \begin{Bmatrix} n-1\\ k \end{Bmatrix}\)

  2. \(x^n=\sum_k\begin{Bmatrix}n\\ k\end{Bmatrix}x^{\underline k}\) (展开可证,组合意义即\(x\)种颜色的球选\(n\)\(=\)枚举一共选了\(k\)种颜色划分的方案数乘从\(x\)中颜色选出\(k\)个进行排列的方案数)

  3. \(x^n=\sum_k\begin{Bmatrix}n\\ k\end{Bmatrix}(-1)^{n-k}x^{\overline k}\)

  4. \(\begin{Bmatrix}n\\k\end{Bmatrix}=\frac{1}{k!}\sum\limits_{i=0}^k(-1)^i\binom{i}{k}(k-i)^n\) (就是令集合间有序,然后枚举有几个集合是空的进行容斥)

求一行第二类斯特林数:

  • 完全可以用第3个式子直接做了,复杂度\(O(n\log n)\)

斯特林反演

可以把第一类的1式,第二类的1,2式合起来,得到\(\sum\limits_{k=p}^n\begin{Bmatrix}n\\k\end{Bmatrix}\begin{bmatrix}k\\p\end{bmatrix}(-1)^{n-k}=[p=n]\),然后就可以愉快的进行反演,得
\[ f_n=\sum\limits_{i=0}^n\begin{Bmatrix}n\\i\end{Bmatrix}g_i \\ g_n=\sum\limits_{i=0}^n(-1)^{n-i}\begin{bmatrix}n\\i\end{bmatrix}f_i \]

单位根反演

https://blog.csdn.net/DT_Kang/article/details/79944113

\(\frac{1}{n}\sum\limits_{i=0}^{n-1}w^{ki}=[n|k]\)

怎么求原根

\(2\)开始枚举\(g\),检查是否对于所有的\(q,is[q],q|\varphi(p)\)都满足\(g^{\frac{phi}{q}}\not =1\)

置换

https://blog.csdn.net/zhouyuheng2003/article/details/88527913

广义二项式定理

\((1+x)^{-n}=\sum\limits_{i=0}^{\infty}(-1)^{i}\binom{n+i-1}{i}\)

\((1-x)^{-n}=\sum\limits_{i=0}^{n\infty}\binom{n+i-1}{i}\)

posted @ 2019-04-03 17:21 fcwww 阅读(...) 评论(...) 编辑 收藏