生成函数浅谈
Posted mikefeng
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了生成函数浅谈相关的知识,希望对你有一定的参考价值。
羊驼说,要当老师,所以强大的羊驼教会了我们生成函数。
羊驼说,我们有卷积,所以生成函数的问题通常可以在带 \\(log\\) 的时间复杂度内解决这类问题。
普通型生成函数
数列 \\(1,1,1,1,1,1\\) 的普通型生成函数就是 \\(1+x+x^2+x^3+x^4+x^5\\)。
而数列 \\(1,1,\\cdots,1,1,\\cdots\\) 的普通型生成函数就是 \\(1+x+x^2+x^2+\\cdots +x^n+\\cdots\\)。
羊驼说,写成展开形式形式太麻烦,所以羊驼教会了我们封闭形式。
设 \\(F(x)=1+x+x^2+x^3+x^4+x^5\\)
则 \\(xF(x)=x+x^2+x^3+x^4+x^5\\)
所以 \\(F(x)=\\frac1-x^61-x\\)
对于无穷数列也是同理,我们可以假定它收敛,得到封闭形式。
设 \\(F(x)=1+x+x^2+\\cdots\\)
则 \\(xF(x)=x+x^2+x^3+\\cdots\\)
所以 \\(F(x)=\\frac11-x\\)
下面是一些常用的无穷数列普通型生成函数的封闭形式和展开形式的对应关系:
\\(a_i=p^i x^i,F(x)=\\frac11-px\\)
\\(a_i=x^pi,F(x)=\\frac11-x^p\\)
\\(a_i=(i+1)x^i,F(x)=\\frac1(1-x)^2\\)
\\(a_i=\\binom m i x^i,F(x)=(1+x)^m\\)(二项式定理)
指数型生成函数
羊驼说,她不会组合数,所以就有了指数型生成函数。
\\(1,1,\\cdots\\) 的指数型生成函数就是 \\(1+x+\\fracx^22!+\\fracx^33!+\\cdots\\)
指数型生成函数通常用来消掉组合数中的阶乘,并且一般是无穷数列。
对于指数型生成函数的封闭形式和展开形式来说,二者对应关系如下:
因此,指数型生成函数的封闭形式通常是 \\(e\\) 的幂次。
下面是一些常用的无穷数列指数型生成函数的封闭形式和展开形式的对应关系:
\\(a_i=\\fracx^ii!,F(x)=e^x\\)
\\(a_i=(-1)^i\\fracx^ii!,F(x)=e^-x\\)
\\(a_i=\\fracx^2i2i!,F(x)=\\frace^x+e^-x2\\)
\\(a_i=\\fracx^2i+1(2i+1)!,F(x)=\\frace^x-e^-x2\\)
于是我们就学会了生成函数。
例题
羊驼说,要有例题,所以我们来到了 P2000 拯救世界。
两位大神的召唤方法显然都可以写成收封闭形式,只要约一下分,就可以得到最终的封闭形式。
\\(kkksc03\\):
金:\\(F(x)=\\frac11-x^6\\)
木:\\(F(x)=\\frac1-x^101-x\\)
水:\\(F(x)=\\frac1-x^61-x\\)
火:\\(F(x)=\\frac11-x^4\\)
土:\\(F(x)=\\frac1-x^81-x\\)
\\(lzn\\):
金:\\(F(x)=\\frac11-x^2\\)
木:\\(F(x)=\\frac1-x^21-x\\)
水:\\(F(x)=\\frac11-x^8\\)
火:\\(F(x)=\\frac11-x^10\\)
土:\\(F(x)=\\frac1-x^41-x\\)
乘起来可得:
再转换回展开形式:
答案即为 \\(\\binom n+4 4\\)。
可以用 \\(NTT\\) 加速高精度。
羊驼说,这种板子题太简单,所以就有了 P4841 城市规划
我们枚举 \\(1\\) 节点所在的连通块大小,设 \\(f(x)\\) 是合法连通图数量,\\(g(x)\\) 是合法图数量,则可得 \\(g(n)=\\sum_i=1^n \\binom n-1 i-1 f(i)g(n-i)\\)
同时我们已知 \\(g(n)=2^\\binom n 2\\),开始推柿子。
\\(\\beginalignedat22^\\binom n 2&=\\sum_i=1^n \\binom n-1 i-1 f(i)2^\\binom n-i 2\\\\ \\frac2^\\binom n 2(n-1)!&=\\sum_i=1^n \\fracf(i)(i-1)!\\frac2^\\binom n-i 2(n-i)! \\endalignedat\\)
多项式求逆即可。
Python之浅谈生成器
三元表达式
a=0
b=6
print (a)if a>b else print(b)
三元表达式只能写if的双分支结构
列表推导式
print(list(i for i in range(10)))#这种写法只有list和set才有用
字典生成式
print(k:v**3 for k,v in zip([a,b,c,d],[1,2,3,4]))#不能写这种代码,可读性太差
生成器
在Python中创建迭代器最方便的技术是使用生成器。生成器的语法类似于函数,但不返回值。为了显示序列中的每一个元素,会使用yield语句。
def range(start=0,end=None,long=1):#通过生成器来实现range内置方法
if end==None:
start,end=0,start
while start<end:
yield start
start+=long
for i in range(6,10):
print(i)
注意:我们使用关键字yield而不是return来表示结果。这表明在Python中,我们正在定义一个生成器而不是一个传统的函数。在同一函数中,将yield和return语句结合起来是非法的,除非是使生成器结束执行的return语句。
生成器表达式
print(tuple(i for i in range(1000000)))
生成器表达式与列表推导式的区别就是生成器表达式输出的是元组,列表推导式输出的是列表,而元组可以减少占用空间。
匿名函数
匿名函数就是没有名字的函数,匿名需要关键字lambda
匿名函数一般不单独使用,和 filter()/map()/sorted()/列表的sort()内置方法联用
salary_dict =
'tim': 3000,
'jason': 100000,
'tank': 5000,
'sean': 2000
salary_list = list(salary_dict.items())
print(max(salary_list,key=lambda i:i[1]))#求最大值
print(min(salary_list,key=lambda i:i[1]))#求最小值
print(list(filter(lambda i: i[1] < 5000, salary_list))) #筛选出工资小于5000的人
print(list(map(lambda i: i[1] + 2000, salary_list)))#每个人的工资加2000
以上是关于生成函数浅谈的主要内容,如果未能解决你的问题,请参考以下文章