生成函数知识总结

生成函数知识总结生成函数基础知识 OJ 练习 FruitHDU 2152 普通生成函数 排列组合 HDU 1521 指数生成函数 Ignatiusandt 1028 普通生成函数 HoldingBin LadenCaptive HDU 1085 普通生成函数 悼念 512 汶川大地震遇难同胞 来生一起走 HDU 2189 普通生成函数 BZOJ3028 食物 普通生成函数 推导 欧拉降幂 E CountingSequ

基础知识

(1)普通生成函数: k k k 种元素的多重集合的 r r r 组合数(有限和无限多重集都可以)

  • 数列:1,1, 1, 1, 1的生成函数,也可以表示一个因子的限制
    g ( x ) = 1 + x + x 2 + ⋯ + x n + ⋯ = ∑ n = 0 ∞ x n = 1 1 − x g(x)=1+x+x^2+\dots+x^n+\dots=\sum_{n=0}^{\infty} x^n =\frac 1{1-x} g(x)=1+x+x2++xn+=n=0xn=1x1
  • e 1 + e 2 + ⋯ + e k = n e_1+e_2+\dots+e_k=n e1+e2++ek=n 的正整数解为: C n + k − 1 n C_{n+k-1}^n Cn+k1n。其生成函数如下
    g ( x ) = ∑ n = 0 ∞ C n + k − 1 n x n = 1 ( 1 − x ) k g(x)=\sum_{n=0}^{\infty}C_{n+k-1}^n x^n=\frac {1}{(1-x)^k} g(x)=n=0Cn+k1nxn=(1x)k1

(2)指数生成函数: k k k 种元素的多重集合的 r r r 排列数(有限和无限多重集都可以)

(3)生成函数次数表示选择物品的次数

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

解题方法

对于直接可计算公式的题目
生成函数为: g ( x ) = ( 1 + x + x 2 + …   ) ( 1 + x 2 + x 4 + …   ) ( 1 + x 3 + x 6 + …   ) … g(x)=(1+x+x^2+\dots)(1+x^2+x^4+\dots)(1+x^3+x^6+\dots)\dots g(x)=(1+x+x2+)(1+x2+x4+)(1+x3+x6+) 请你计算 x m x^m xm 的系数

解题步骤

练习题

HDU – 2152 Fruit (普通生成函数)

链接:http://acm.hdu.edu.cn/showproblem.php?pid=2152

题意:有 n 种水果,每种水果出现的次数在 [ a i , b i ] [a_i,b_i] [ai,bi] 之间,问一共买 m 个水果有多少种购买方案?

思路 ( x a 1 + ⋯ + x b 1 ) ( x a 2 + ⋯ + x b 2 ) … ( x a n + ⋯ + x b n ) (x^{a_1}+\dots+x^{b_1})(x^{a_2}+\dots+x^{b_2})\dots(x^{a_n}+\dots+x^{b_n}) (xa1++xb1)(xa2++xb2)(xan++xbn) 对这个生成函数求 x m x^m xm 的系数

#include <bits/stdc++.h> using namespace std; int n,m; int a[110],b[110],C1[110],C2[110]; int solve() { 
    for(int i=0;i<=m;++i) C1[i]=C2[i]=0; for(int i=a[1];i<=b[1];++i) C1[i]=1; for(int i=2;i<=n;++i) { 
    for(int j=0;j<=m;++j) for(int k=a[i];k<=b[i];++k) C2[j+k]+=C1[j]; for(int j=0;j<=m;++j) C1[j]=C2[j],C2[j]=0; } return C1[m]; } int main() { 
    while(~scanf("%d%d",&n,&m)) { 
    for(int i=1;i<=n;++i) scanf("%d%d",&a[i],&b[i]); printf("%d\n",solve()); } return 0; } 

HDU – 1521 排列组合 (指数生成函数)

链接:http://acm.hdu.edu.cn/showproblem.php?pid=1521

题意:有 n 种物品,每种物品的数量为 a i a_i ai ,问取 m 个物品的排列数

思路 ( 1 + x + x 2 2 ! + ⋯ + x a 1 a 1 ! ) ( 1 + x + x 2 2 ! + ⋯ + x a 2 a 2 ! ) … ( 1 + x + x 2 2 ! + ⋯ + x a n a n ! ) (1+x+\frac {x^2}{2!}+\dots+\frac {x^{a_1}}{a_1!})(1+x+\frac {x^2}{2!}+\dots+\frac {x^{a_2}}{a_2!})\dots(1+x+\frac {x^2}{2!}+\dots+\frac {x^{a_n}}{a_n!}) (1+x+2!x2++a1!xa1)(1+x+2!x2++a2!xa2)(1+x+2!x2++an!xan) 对这个式子求 x m m ! \frac {x^m}{m!} m!xm 的系数

#include <bits/stdc++.h> using namespace std; int n,m; int a[110],b[110]; double fac[110]; double C1[110],C2[110]; void init() { 
    fac[0]=fac[1]=1; for(int i=2;i<=100;++i) fac[i]=fac[i-1]*i; } double solve() { 
    for(int i=0;i<=m;++i) C1[i]=C2[i]=0; for(int i=0;i<=a[1];++i) C1[i]=1.0/fac[i]; for(int i=2;i<=n;++i) { 
    for(int j=0;j<=m;++j) for(int k=0;k<=a[i];++k) C2[j+k]+=C1[j]*1.0/fac[k]; for(int j=0;j<=m;++j) C1[j]=C2[j],C2[j]=0; } return C1[m]*fac[m]; } int main() { 
    init(); while(~scanf("%d%d",&n,&m)) { 
    for(int i=1;i<=n;++i) scanf("%d",&a[i]); printf("%.0lf\n",solve()); } return 0; } 

HDU – 1028 Ignatius and the Princess III (普通生成函数)

链接:http://acm.hdu.edu.cn/showproblem.php?pid=1028

题意:将整数 n n n 拆分成正整数相加的形式,问有几种组合

思路:每一个小于 n n n 的正整数都有可能组成。共有 n n n个因子,可以得到生成函数
g ( x ) = ( 1 + x + x 2 + …   ) ( 1 + x 2 + x 4 + …   ) ( 1 + x 3 + x 6 + …   ) … g(x)=(1+x+x^2+\dots)(1+x^2+x^4+\dots)(1+x^3+x^6+\dots)\dots g(x)=(1+x+x2+)(1+x2+x4+)(1+x3+x6+)

x n x^n xn的系数就是所求的组合方式

#include <bits/stdc++.h> using namespace std; int n,c1[130],c2[130]; int solve(int m) { 
    for(int i=0; i<=m; ++i) c1[i]=c2[i]=0; for(int i=0; i<=m; ++i) c1[i]=1; for(int i=2; i<=m; ++i) { 
    for(int j=0; j<=m; ++j) for(int k=0; k<=m&&j+k<=m; k+=i) c2[j+k]+=c1[j]; for(int j=0; j<=m; ++j) c1[j]=c2[j],c2[j]=0; } return c1[m]; } int main() { 
    while(~scanf("%d",&n)) printf("%d\n",solve(n)); return 0; } 

HDU – 1085 Holding Bin-Laden Captive! (普通生成函数)

链接:http://acm.hdu.edu.cn/showproblem.php?pid=1085

题意:由面值为1、2、5的硬币不能组成的最小面值是多少。

思路:可以得到生成函数
g ( x ) = ( 1 + x + x 2 + …   ) ( 1 + x 2 + x 4 + …   ) ( 1 + x 5 + x 10 ) g(x)=(1+x+x^2+\dots)(1+x^2+x^4+\dots)(1+x^5+x^{10}) g(x)=(1+x+x2+)(1+x2+x4+)(1+x5+x10)
从小到大遍历系数,为 0 的那一项就是不能组成的

#include <bits/stdc++.h> using namespace std; int n,a[4],b[4],c1[8005],c2[8005]; void solve(int m) { 
    for(int i=0; i<=m; ++i) c1[i]=c2[i]=0; for(int i=0; i<=a[1]; ++i) c1[i]=1; for(int i=2; i<=3; ++i) { 
    for(int j=0; j<=m; ++j) for(int k=0; k<=a[i]*b[i]&&j+k<=m; k+=b[i]) c2[j+k]+=c1[j]; for(int j=0; j<=m; ++j) c1[j]=c2[j],c2[j]=0; } } int main() { 
    while(scanf("%d%d%d",&a[1],&a[2],&a[3])&&(a[1]||a[2]||a[3])) { 
    b[2]=2,b[3]=5; int m=a[1]*1+a[2]*2+a[3]*5; solve(m); int x=1; while(x<=m&&c1[x]) x++; printf("%d\n",x); } return 0; } 

HDU – 2189 悼念512汶川大地震遇难同胞——来生一起走 (普通生成函数)

链接:http://acm.hdu.edu.cn/showproblem.php?pid=2189

题意:把n个人分成几个小组。每个小组的人数必须是素数

思路:用素数组成n,但是不知道用具体多少个素数。每一个小于等于 n 的素数都是一个因子。
可以得到生成函数:
g ( x ) = ( 1 + x 2 + x 4 + x 6 + …   ) ( 1 + x 3 + x 6 + …   ) ( 1 + x 5 + x 10 + …   ) g(x)=(1+x^2+x^4+x^6+\dots)(1+x^3+x^{6}+\dots)(1+x^5+x^{10}+\dots) g(x)=(1+x2+x4+x6+)(1+x3+x6+)(1+x5+x10+)
x n x^n xn的系数就是这个组合数的答案


BZOJ3028: 食物(普通生成函数 + 推导 + 欧拉降幂)

Description
明明这次又要出去旅游了,和上次不同的是,他这次要去宇宙探险!
我们暂且不讨论他有多么NC,他又幻想了他应该带一些什么东西。理所当然的,你当然要帮他计算携带N件物品的方案数。
他这次又准备带一些受欢迎的食物,如:蜜桃多啦,鸡块啦,承德汉堡等等
当然,他又有一些稀奇古怪的限制:
每种食物的限制如下:
(1)承德汉堡:偶数个
(2)可乐:0个或1个
(3)鸡腿:0个,1个或2个
(4)蜜桃多:奇数个
(5)鸡块:4的倍数个
(6)包子:0个,1个,2个或3个
(7)土豆片炒肉:不超过一个。
(8)面包:3的倍数个












注意,这里我们懒得考虑明明对于带的食物该怎么搭配着吃,也认为每种食物都是以‘个’为单位(反正是幻想嘛),只要总数加起来是N就算一种方案。因此,对于给出的N,你需要计算出方案数,并对10007取模

思路:很明显示生成函数的题,并且考虑的是组合数
可以得到生成函数:
g ( x ) = ( 1 + x 2 + …   ) ( 1 + x ) ( 1 + x + x 2 ) ( x + x 3 + …   ) ( 1 + x 4 + x 8 + …   ) ( 1 + x + x 2 + x 3 ) ( 1 + x ) ( 1 + x 3 + x 6 + …   ) g(x)=(1+x^2+\dots )(1+x)(1+x+x^2)(x+x^3+\dots)(1+x^4+x^8+\dots)(1+x+x^2+x^3)(1+x)(1+x^3+x^6+\dots) g(x)=(1+x2+)(1+x)(1+x+x2)(x+x3+)(1+x4+x8+)(1+x+x2+x3)(1+x)(1+x3+x6+)

g ( x ) = 1 1 − x 2 ( 1 + x ) 1 − x 3 1 − x x 1 1 − x 2 1 1 − x 4 ( 1 − x 4 1 − x ) ( 1 + x ) 1 1 − x 3 g(x)=\frac 1{1-x^2}(1+x)\frac {1-x^3}{1-x}x\frac 1{1-x^2}{\frac {1}{1-x^4}}(\frac {1-x^4}{1-x})(1+x)\frac 1{1-x^3} g(x)=1x21(1+x)1x1x3x1x211x41(1x1x4)(1+x)1x31

g ( x ) = x ( 1 − x ) 4 = ∑ n = 0 ∞ C n + 4 − 1 3 x n + 1 = ∑ n = 0 ∞ C n + 2 3 x n g(x)=\frac x{(1-x)^4}=\sum_{n=0}^{\infty}C_{n+4-1}^3x^{n+1}=\sum_{n=0}^{\infty}C_{n+2}^3x^n g(x)=(1x)4x=n=0Cn+413xn+1=n=0Cn+23xn
因此,答案就是 a n = C n + 2 3 a_n=C_{n+2}^3 an=Cn+23
在这里插入图片描述

#include<bits/stdc++.h> #define ll long long using namespace std; const int Maxn=510; const int mod=10007; char s[Maxn]; ll QuickPower(ll base,ll n) { 
    ll ret=1; while(n) { 
    if(n&1) ret=(ret*base)%mod; n>>=1; base=(base*base)%mod; } return ret; } int main() { 
    scanf("%s",s+1); int n=0,len=strlen(s+1); for(int i=1;i<=len;i++) n=(n*10%mod+s[i]-'0')%mod; ll ans=n*(n+1)%mod*(n+2)%mod*QuickPower(6,mod-2)%mod; printf("%lld\n",ans); } 

2019 ICPC上海网络赛 E. Counting Sequences II (指数生成函数 + 推导)

链接:https://nanti.jisuanke.com/t/41413

题意:给定n个位置,对于每一个数 a i a_i ai,都满足 1 ≤ a i ≤ m 1\le a_i \le m 1aim,并且如果 a i a_i ai是偶数的话, a i a_i ai出现的次数是偶数次,求排列的个数

思路:求的是排列,所以是指数型生成函数。在[1,m]的范围内,相当于有m个因子,每个因子分别代表对 1 、 2 、 3 、 4 、 … 、 m 1、2、3、4、\dots、m 1234m各自的限制。其中偶数有 f l o o r ( m 2 ) floor(\frac m2) floor(2m)个,奇数有 m − f l o o r ( m 2 ) m-floor(\frac m2) mfloor(2m),设 t = f l o o r ( m 2 ) t=floor(\frac m2) t=floor(2m),可以得到指数型生成函数
g ( x ) = ( 1 + x + x 2 2 ! + x 3 3 ! + …   ) m − t ( 1 + x 2 2 ! + x 4 4 ! + …   ) t g(x)=(1+x+\frac {x^2}{2!}+\frac {x^3}{3!}+\dots)^{m-t}(1+\frac {x^2}{2!}+\frac {x^4}{4!}+\dots)^{t} g(x)=(1+x+2!x2+3!x3+)mt(1+2!x2+4!x4+)t
化简可得:
g ( x ) = e x ( m − t ) ( e x + e − x 2 ) t = e x ( m − t ) ∑ i = 0 t C t i e x ( t − i ) e − x i 2 t g(x)=e^{x(m-t)}(\frac {e^x+e^{-x}}2)^t=\frac{e^{x(m-t)}\sum_{i=0}^tC_t^ie^{x(t-i)}e^{-xi}}{2^t} g(x)=ex(mt)(2ex+ex)t=2tex(mt)i=0tCtiex(ti)exi
g ( x ) = ∑ i = 0 t C t i e ( m − 2 i ) x 2 t = ∑ n = 0 ∑ i = 0 t C t i ( m − 2 i ) n 2 t x n n ! g(x)=\frac {\sum_{i=0}^tC_t^ie^{(m-2i)x}}{2^t}=\sum_{n=0}\frac{\sum_{i=0}^tC_t^i{(m-2i)^n}}{2^t}\frac {x^n}{n!} g(x)=2ti=0tCtie(m2i)x=n=02ti=0tCti(m2i)nn!xn
因此可以得到 a n = ∑ i = 0 t C t i ( m − 2 i ) n 2 t a_n=\frac{\sum_{i=0}^tC_t^i{(m-2i)^n}}{2^t} an=2ti=0tCti(m2i)n a n a_n an就是答案




#include <bits/stdc++.h> #define ll long long using namespace std; const int mod=1e9+7; int t,m; ll n; int qpow(int b,int n,int mod) { 
    int res=1; while(n) { 
    if(n&1) res=1ll*res*b%mod; n>>=1; b=1ll*b*b%mod; } return res; } const int N=2e5; int fac[N+10],finv[N+10]; void init() { 
    fac[0]=fac[1]=1; for(int i=2; i<=N; ++i) fac[i]=1ll*fac[i-1]*i%mod; finv[N]=qpow(fac[N],mod-2,mod); for(int i=N-1; i>=0; --i) finv[i]=1ll*finv[i+1]*(i+1)%mod; } int C(int n,int m) { 
    return 1ll*fac[n]*finv[m]%mod*finv[n-m]%mod; } int main() { 
    init(); scanf("%d",&t); while(t--) { 
    scanf("%lld%d",&n,&m); n%=mod-1; int ans=0; int t=m/2; for(int i=0; i<=t; ++i) ans=(ans+1ll*C(t,i)*qpow(m-2*i,n,mod)%mod)%mod; ll res=qpow(2,t,mod); ans=1ll*ans*qpow(res,mod-2,mod)%mod; printf("%d\n",ans); } return 0; } 
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/230290.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • mysql时间戳格式转换日期格式字符串

    mysql时间戳格式转换日期格式字符串1.测试表表结构CREATETABLE`timestamp_string_change`(`id`intNOTNULLAUTO_INCREMENT,`up_time`timestampNULLDEFAULTNULL,PRIMARYKEY(`id`))ENGINE=InnoDBAUTO_INCREMENT=2DEFAULTCHARSET=utf8mb4COLLATE=utf8mb4_0900_ai_ci;2.mysql时间戳格式转字符串方法1

    2022年6月21日
    163
  • R语言画图时常见问题

    各位朋友,我已开通微信公共号:小程在线我会把文章及时的更新到公共号上,欢迎大家的关注。1如何在同一画面画出多张图?修改绘图参数,如par(mfrow=c(2,2))或par(mfcol=c(2,2));par():mar设置图离四个边缘的距离;bg设置背景颜色;xaxt和yaxt设置坐标轴标签的类型(=”n”表示不画轴标签);xlim和ylim设置坐标轴的范围…

    2022年4月7日
    31
  • cs与bs模式的优缺点_什么是cs什么是bs

    cs与bs模式的优缺点_什么是cs什么是bscs与bs模式关于CS(Client-Server)模式和BS(Browser-Server)模式的水很深,盆地自己也认为对此了解不够透彻,但作为手机客户端设计,如果不对CS、BS做一定程度的了解,是很容易出现一些方向性的错误、走一些弯路抑或在实现性价比上付出过多代价。本文偏向于基础知识,产品人员很多情况下不仅仅要了解表现、交互,还需要一定程度上了解可实现性、实现代价、实现形式、实现限制等…

    2025年10月11日
    6
  • WP系统推广难的原因之中的一个之我见

    WP系统推广难的原因之中的一个之我见

    2022年1月30日
    59
  • LOAM 论文及原理分析「建议收藏」

    LOAM 论文及原理分析「建议收藏」前言:由于对三维激光SLAM比较感兴趣,并且最近也在找无人驾驶激光SLAM算法的岗位,所以花了一个多月把LOAM的论文和源码好好看了一遍。发现论文还是比较容易明白,但一看代码全是坑。看论文懂了,看代码似懂非懂。为了尽快把这坑填上,所以诚邀读者一起探讨。作者始终认为填坑最好的方法是拉别人和你一起填坑。由于三千多行的源码不是一篇博客能够讲明白的,所以这篇博客主要讲一下我对LOAM论文…

    2022年5月11日
    36
  • layui 弹出层和提交表单

    layui 弹出层和提交表单在点击修改按钮的时候,content路径CPTL/+curId ,路径中的curid是当前信息的ID,弹窗跳出当前的数据信息 2. 把提交的按钮写在子页面里面,这里没有用layui自带的yes:function(), 3….

    2022年6月12日
    81

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号