指数生成函数

指数生成函数

定义:F(x)=n0anxnn!

<1,1,1,>⟶1+x1!+x22!+x33!+=n0xnn!=ex

<1,p,p2,>⟶1+px1!+p2x22!+p3x33!+=n0pnxnn!=epx

加减运算:

F(x)±G(x)=i0aixii!±j0bjxjj!=n0(an±bn)xnn!

卷积:

F(x)G(x)=i0aixii!j0bjxjj!=n0xni=0naibni1i!(ni)!=n0xnn!i=0nn!i!(ni)!aibni=n0xnn!i=0nCniaibni

n=i+j

用处:不同于普通生成函数,指数生成函数用来解决多重集排列数问题。

HDU-1521 排列组合:

n 种物品,每种物品 ai 个,问取 m 个物品的排列数?

设个每种物品中取 bi 个,0biaim=i=1nbi,对于一组选定的 bi 进行排列的方案数为 m!b1!b2!bn!。意思是 m 的全排列去掉每一组中的重复。

例如取3个A、1个B的排列数为 4!3!1!=246=4,即AAAB,AABA,ABAA,BAAA。

那么所有满足 b1+b2++bn=m 的排列数之和,即答案。

构造指数生成函数:第1种物品的生成函数为 (1+x11!+x22!++xa1a1!),第 n 种物品的生成函数为 (1+x11!+x22!++xanan!)

(1+x11!+x22!++xa1a1!)(1+x11!+x22!++xa2a2!)(1+x11!+x22!++xanan!)

xmm! 的系数。

做乘法:xb1b1!×xb2b2!××xbnbn!=xb1+b2++bnb1!b2!bn!=xmb1!b2!bn!=m!b1!b2!bn!xmm!

做卷积,所有满足b1+b2++bn=m 的项的系数之和,再乘以 m!,即为答案。

求系数的方法还是累加。需要预处理阶乘。

代码:

int n,m;
int a[11];
double fac[11];
double C[11],D[22];

void init(){//计算阶乘
  fac[0]=fac[1]=1;
  for(int i=2;i<=100;++i)
    fac[i]=fac[i-1]*i;
}
double calc(){
  for(int i=0;i<=m;++i) C[i]=D[i]=0;
  for(int i=0;i<=a[1];++i) C[i]=1.0/fac[i];
  for(int i=2;i<=n;++i){
    //计算x^(j+k)的系数
    for(int j=0;j<=m;++j)
      for(int k=0;k<=a[i];++k)
        D[j+k]+=C[j]/fac[k];
    //转存C,清空D    
    for(int j=0;j<=m;++j)
      C[j]=D[j], D[j]=0;
  }
  return C[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",calc());
  }
  return 0;
}
posted @   Vegdie  阅读(132)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示