学习笔记第四十节:生成函数

本文深入探讨了生成函数的定义与应用,包括普通生成函数与指数生成函数的区别,以及如何通过生成函数解决复杂的组合数卷积问题。文章详细介绍了多项式求逆、泰勒展开、对数求导等技巧在生成函数中的应用,展示了如何将问题简化并求解。

正题

      以前讲的东西并不是没有道理,但是如果要更严格地讨论生成函数,我们就要学习他的定义。

      普通生成函数:F(x)=\sum_{i=0}^{\infty} f_ix^i

      指数生成函数:G(x)=\sum_{i=0}^{\infty} g_i\frac{x^i}{i!}

      指数生成函数就是普通生成函数多了一个\frac{1}{i!}

      这个暂时先记下来,后面再讲有什么用。


      先讲讲组合数卷积

      如果题目给出两个多项式,要你求他们的组合数卷积,什么意思呢?

      也就是给出两个多项式A(x),B(x),要你求一个C(x)|[x^k]C(x)=\sum_{i=0}^k C_k^i a_ib_{k-i}

      这个怎么做?把组合数拆一拆就好了。 

      也就是将a_i\to \frac{a_i}{i!},b_i\to \frac{b_i}{i!}

      将两个多项式卷起来,然后再将c_i\to c_ii!就好了。


      当题目给出一系列多项式系数的时候,要你求的可能不是简单的卷积操作,或者简单的组合数卷积操作。

      而是要你求[x^n]G(x)=\sum_{i=0}^{\infty} A(x)^i,保证[x^0]A(x)=0,怎么办!

      暴力的话,我们可以直接将暴力卷n次,把第n项加起来就可以了。

      但是考虑一系列优美的泰勒展开式:

  1. e^x=\sum_{i=0}^{\infty} \frac{x^i}{i!}
  2. \frac{1}{1-x}=\sum_{i=0}^{\infty} x^i
  3. \ln(1+x)=\sum_{i=0}^{\infty} (-1)^i\frac{x^{i+1}}{(i+1)!}
  4. sin(x)=\sum_{i=0}^{\infty} (-1)^i\frac{x^{2i+1}}{(2i+1)!}
  5. cos(x)=\sum_{i=0}^{\infty} (-1)^i\frac{x^{2i}}{(2i)!}
  6. \frac{e^x+e^{-x}}{2},\frac{e^x-e^{-x}}{2}可以自己试着推导一下。

      发现G(x)=\sum_{i=0}^{\infty} A(x)^i=\frac{1}{1-A(x)}

      可以多项式求逆解决。

      再比如说,现在有F(x)=\sum_{i=0}^{\infty} \frac{B(x)^i}{i!}=e^{B(x)}

      就可以多项式exp解决,假设现在知道F,要求B,也可以多项式ln解决。

      所以我们使用生成函数不是为了简单的卷积,而是因为生成函数在i\to\infty的时候收敛。

      那么我们就可以使用泰勒展开式把它转化为一些优美的形式。从而使问题得到解决

      所以指数生成函数与普通生成函数的区别就在于,指数生成函数是处理组合数卷积的一种方法,仅此而已。

      背熟式子,练好多项式全家桶,这部分就完了。


      对于一串数字,我们可以把它写成一条函数,以便于化简和计算。

      比如说(2,3,5),那么这个数列的生成函数就是F(x)=2+3x+5x^2,而其中的x是没有意义的,真正有意义的只有系数,所以我们在化简式子时,x可以取任意实数。

      用生成函数以及一些关于对数、求导之类的数学方法,我们可以把问题简化。

      比如说,我们要求(\sum_{i=1}^n 1,\sum_{i=1}^na_i,\sum_{i=1}^na_i^2,...,\sum_{i=1}^na_i^t)

      如果暴力枚举,我们就需要O(n^2)的时间,但是,我们看看生成函数怎么把这个式子简化。

      首先构造生成函数F(x)=\sum_{i=1}^n\sum_{j=0}^ta_i^jx^j

      发现第i项的系数恰好是数列中的第i个数。

      所以,我们继续化简这个式子,只要求出每一项的系数就可以了。

      因为x取任何值都可以,那我们就让x\to 0 ,x\not =0

      所以,利用等比数列求和可以得到:

      F(x)=\sum_{i=1}^n\frac{1}{1-a_ix} \\=\sum_{i=1}^n1-\frac{-a_ix}{1-a_ix} \\=n-x\sum_{i=1}^n\frac{-a_ix}{1-a_ix}

      接着,我们发现\frac{-a_ix}{1-a_ix}=\ln(1-a_ix)\ln(1-a_ix)=\ln '(1-a_ix)*(1-a_ix)'=\frac{-a_ix}{1-a_ix}

      换一下,发现:

      F(x)=n-x\sum_{i=1}^n(\ln(1-a_ix))' \\=n-x(\ln(\prod_{i=1}^n(1-a_ix)))' \\=n-x(\frac{1}{\prod_{i=1}^n(1-a_ix)}*(\prod_{i=1}^n(1-a_ix))')

      所以,我们只需要分治FFT求出\prod_{i=1}^n (1-a_ix),然后再对这个东西求一个逆,再求一个导,最后卷积之后,向右偏移一位,取负,再加上n即可。具体怎么分治FFT,你只需要,不断地用NTT/FFT来合并最底层的两个多项式就可以了,这样的时间复杂度是O(n(\log_2n)^2)的。

      那么时间复杂度就降到了O(n(\log_2n)^2)

      这就很好地证明了生成函数可以解决一些很复杂的问题。

      接着上面有一些对数求导以及积分的概念,这里讲一下:

      首先我们要知道,积分是求导的反函数,对数是exp的反函数。

      就是  \int G'=G=\ln(\exp(G))

      接着\ln'x=(\ln x)'=\frac{1}{x}的。

      因为根据链式法则(f(g(x)))'=f'(g(x))*g'(x),所以(\ln x)'=\ln'x *x'=\ln'x

      怎么求一个多项式的对数呢?

      首先我们可以先把对数的导求出来,在求积分就是答案,因为他们俩是反函数啊。

      也就是说\ln A(x)=\int (\ln A(x))'=\int \frac{1}{A(x)}*A(x)'

      

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值