bzoj 2839 集合计数——二项式反演

Posted narh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 2839 集合计数——二项式反演相关的知识,希望对你有一定的参考价值。

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2839

设 ( g(i) ) 表示至少有 i 个, ( f(i) ) 表示恰好有 i 个,则

( g(i)=C_{n}^{i}*(2^{2^{n-i}}-1) )

( g(i)=sumlimits_{j=i}^{n}C_{j}^{i}f(j) )

( f(i)=sumlimits_{j=i}^{n}(-1)^{j-i}C_{j}^{i}g(j) )

以为把 g 写出来后 ( C_{n}^{i}*C_{i}^{j} = C_{n}^{j} ) ,然而其实 ( C_{n}^{i}*C_{i}^{j} = C_{n}^{j}*C_{n-j}^{i-j} ) 。

注意指数取模是 mod-1 。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int N=1e6+5,mod=1e9+7;
int n,k,g[N],jc[N],jcn[N];
void upd(int &x){x>=mod?x-=mod:0;x<0?x+=mod:0;}
int pw(int x,int k,int md=mod)
{int ret=1;while(k){if(k&1)ret=(ll)ret*x%md;x=(ll)x*x%md;k>>=1;}return ret;}
void init()
{
  jc[0]=1;for(int i=1;i<=n;i++)jc[i]=(ll)jc[i-1]*i%mod;
  jcn[n]=pw(jc[n],mod-2);for(int i=n-1;i>=0;i--)jcn[i]=(ll)jcn[i+1]*(i+1)%mod;
}
int C(int n,int m)
{return (ll)jc[n]*jcn[m]%mod*jcn[n-m]%mod;}
int main()
{
  scanf("%d%d",&n,&k);
  init();
  int ans=0;
  for(int i=k,j=1;i<=n;i++,j=-j)
    ans=(ans+(ll)j*C(i,k)*C(n,i)%mod*(pw(2,pw(2,n-i,mod-1))-1))%mod,upd(ans);
  printf("%d
",ans);
  return 0;
}

 

以上是关于bzoj 2839 集合计数——二项式反演的主要内容,如果未能解决你的问题,请参考以下文章

bzoj2839 集合计数

bzoj 2839集合计数

bzoj2839 集合计数

bzoj2839 集合计数(容斥)

bzoj2839: 集合计数 容斥+组合

BZOJ2839集合计数 组合数+容斥