生成函数

Posted 66t6

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了生成函数相关的知识,希望对你有一定的参考价值。

生成函数

标签(空格分隔): 数学 生成函数 多项式 笔记


概述

比以前讲的多了很多,其中补充了多项式求逆和(ln)

生成函数一般用于统计( ext{size}=n)的数量

技术图片

如下图每个节点( ext{size}=1)被称为( ext{atom})

(e.g.)

  • (n)个点有标号无连通图数量
  • 黑白点旋转同构(n)元环数量
  • (n)个点平面图

前置知识

多项式求逆

(A(x)B(x)equiv 1pmod {x^n})
(A(x)B(x)-1equiv 0pmod {x^n})
((A(x)B(x)-1)^2equiv 0pmod {x^{2n}})
(A(x)(2B(x)-B(x)^2A(x))equiv 1pmod {x^{2n}})
问题转为父问题,迭代(log)次即可,一个
(T(n)=O(nlg n)+T(n/2)=O(nlg n))

inline void Inv(re int a[],re int b[],re int n){
    re int i,len;b[0]=qpow(a[0],mod-2);static int t[N];memset(t,0,n<<2);
    for(len=4;len<=n;len<<=1){
        memcpy(t,a,(len>>1)<<2);
        Getrev(len);NTT(t,len,1),NTT(b,len,1);
        for(i=0;i<len;++i)b[i]=Modup(((b[i]<<1)-1ll*t[i]*b[i]%mod*b[i])%mod);
        NTT(b,len,-1);
        memset(b+(len>>1),0,(len>>1)<<2);
    }
}

多项式(ln)

(A(x)=1+sumlimits_{ige 1}a_ix^i)(注意常数项不为1的多项式无法求导)

(displaystyle{ln(A(x))=int ln(A(x))'=int frac{A(x)'}{A(x)}})

就是一个多项式求导+积分+求逆

inline void derive(re int a[],re int len){re int i;for(i=1;i<len;++i)a[i-1]=1ll*i*a[i]%mod;a[len-1]=0;}
inline void intgral(re int a[],re int len){re int i;for(i=len;~i;--i)a[i+1]=1ll*a[i]*inv[i+1]%mod;a[0]=0;}
inline void Ln(re int a[],re int b[],re int len,re int n){
    re int i;Inv(a,b,len);derive(a,n);Getrev(len);
    NTT(a,len,1),NTT(b,len,1);
    for(i=0;i<len;++i)b[i]=1ll*a[i]*b[i]%mod;
    NTT(b,len,-1);intgral(b,n);
    memset(b+n,0,(len-n)<<2);
}

普通生成函数(OGF)

概述

用来解决无标号计数问题

对组合对象(A)

(displaystyle{F(x)=sum_{ain A}x^{size(a)}=sum_{i}Aa_ix_i})

其中(a_i)表示组合对象中(size=i)的元素个数

([x^n]F(x))(F(x))(x_n)的系数

乘法原理

定义两个集合的笛卡尔积为
(A*B={(a,b)mid ain A,bin B})
表示(A,B)集合的有序拼接
(displaystyle{C(x)=A(x)B(x)=sum_{ain A}sum_{bin B}x^{size(a)+size(b)}})
可以转为枚举(size)形式的多项式乘法,证明了生成函数的乘积是组合对象有序拼接

例题

(large{mathtt{BSOJ4763}}):模板

偶数 (<1,0,1,0,1,0>Rightarrow F(x)=frac{1}{1-x^2})

(3)的倍数 (<1,0,0,1,0,0>Rightarrow F(x)=frac{1}{1-x^3})

(4)的倍数 (<1,0,0,0,1,0>Rightarrow F(x)=frac{1}{1-x^4})

0或1个(<1,1,0,0,0,0>Rightarrow F(x)=frac{1}{1-x}-frac{x^2}{1-x} =frac{1-x^2}{1-x}=1+x)

不超过一个(同上)(<1,1,0,0,0,0>Rightarrow F(x)=frac{1-x^2}{1-x}=1+x)

0,1或2个(<1,1,1,0,0,0>Rightarrow F(x)=frac{1}{1-x}-frac{x^3}{1-x} =frac{1-x^3}{1-x})

0,1,2或3个(<1,1,1,1,0,0>Rightarrow F(x)=frac{1}{1-x}-frac{x^4}{1-x} =frac{1-x^4}{1-x})

奇数 (<0,1,0,1,0,1>Rightarrow F(x)=frac{x}{1-x^2})

根据乘法原理累乘得(F(x)=frac{x}{(1-x)^4}=(1-x)^{-4}*x)

首先二项式展开(displaystyle)

[F(x)=xsum_{i=0}^∞inom{3+i}{i}x^i =sum_{i=0}^∞inom{3+i}{i}x^{i+1} =sum_{i=1}^∞inom{2+i}{3}x^i]

所求([x^n]F(x)=inom{2+n}{3})

(large{(无来源)骨牌计数:})(i)(a_i)个求和为(n)的方案数

(1)个骨牌就是(mathtt{atom}),设每个数(骨牌)的EGF为(A(x)=sumlimits_i a_ix^i)则最后拼出结果即计数对象可由若干个(mathtt{atom})有序拼接构成,有前面可知,这种拼接就是乘法
[F(x)=sum_{i=0}^{infty} A^i(x)=frac{1}{1-A(x)}]
这被称作一个(mathtt{atom})的生成序列记做(SEQ(A(x)))

(large无来源平面树:)(n)个节点有根儿子有序树个数(largemathtt{/BSOJ4758}):求(n)个节点有根二叉树的叶子结点期望

这两道题专门开一篇

(largemathtt{BSOJ4370}):求(n)个数中任选三个数组成三角形的概率

(largemathtt{BSOJ4705}):求(n)个正整数任取(1,2,3)个的和的每个可能取值的方案数

设本题( ext{size})为和

(A/B/C(x))表示同一个斧头重复一/二/三次价值为(x)的斧头个数

(A^2(x)),会产生((x_i,x_i))同一把斧头的贡献,所以定义(B(x))为同一个斧头重复两次的方案数,那么(A^2(x)-B(x))就是两把斧头时真正的贡献,又因为与顺序无关,所以还要除以(2)

然后(A^3(x))的话,可能会有一把斧头重复两次或三次,如果重复两次,那么就是((x_i,x_i,y_i),(x_i,y_i,x_i),(y_i,x_i,x_i)),就是(3A(x)B(x)),但是减去这个的话又会把((x_i,x_i,x_i))的情况多减去两次,所以定义(C(x))为同一把斧头重复三次的生成函数,于是还要加上(2C(x)),然后无关顺序的话还要除掉(3!=6)

综上,最终的答案的EGF为(F(x)=A(x)+frac{A^2(x)-B(x)}{2}+frac{A^3(x)-3A(x)B(x)+2C(x)}{6})

指数型生成函数(EGF)

概述

有时候,对象的每个(mathtt{atom})之间是存在区别的

给每个(mathtt{atom})标号,这样就能表示两个(mathtt{atom})之间是有区别的

这是一个例子

技术图片

有标号对象是和无标号对象相对应的。

每个有标号对象都可以看作是,无标号对象枚举了所有可能的标号顺序得到的

问题转变为寻找拼接方法使得两个有标号对象拼接起来之后,能和无标号对象拼接起来的东西相对应

方法是重新分配标号,再拼接

对组合对象(A)

[F(x)=sum_i a_ifrac{x^i}{i!}]

分配则在乘积的组合数中体现

[H(x)=F(x)G(x)Leftrightarrow h(n)=sum_i inom{n}{i}f(i)g(n-i)]

以上是关于生成函数的主要内容,如果未能解决你的问题,请参考以下文章

Apollo Codegen 没有找到生成代码的操作或片段

前端开发工具vscode如何快速生成代码片段

前端开发工具vscode如何快速生成代码片段

vscode代码片段生成vue模板

VSCode自定义代码片段——声明函数

VSCode自定义代码片段8——声明函数