(HDU6397)2018 Multi-University Training Contest 8 - 1001 - Character Encoding - (组合数容斥 | 母函数)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6397

题意:有n个数字0~n-1,问任取m个使得总和为k的方案数。(可以重复取)

解析:此题可以用母函数来解,也可以通过组合数容斥来解。

组合数容斥解法:

我们将问题转化为:X个相同的球放入Y个不相同的盒子中,要求每个盒子至多N个球至少0个球,共有多少种不同的放法?正好是知乎上的一个话题https://www.zhihu.com/question/65668587,图中X=k,Y=m,N=n-1;

(HDU6397)2018 Multi-University Training Contest 8 - 1001 - Character Encoding - (组合数容斥 | 母函数)_第1张图片

(图片截图自知乎,侵删)

 

(以下题解来自dls直播,录屏重播地址https://www.bilibili.com/video/av29454041)

母函数解法:

  • 首先可得母函数:(1+x^1+x^2+...+x^(n-1))^m,答案就是此多项式中x^k的系数。
  • 由等比数列公式(1+x^1+x^2+...+x^(n-1)) = (1-x^n) / (1-x);则(1+x^1+x^2+...+x^(n-1))^m=(1-x^n)^m / (1-x)^m=(1-x^n)^m * (1-x)^-m;
  • 由多项式定理(1-x^n)^m= sum( i=0 to m  (-1)^i*C(m,i)*x^(i*n) );
  • 又由某公式得(1-x)^-m= sum( i>=0  x^i*C(m-1+i,m-1) );
  • 母函数可化为:sum( i=0 to m  (-1)^i*C(m,i)*x^(i*n) )  *  sum( i>=0  x^i*C(m-1+i,m-1) );
  • 此多项式中x^k的系数为:sum( i>=0&&i*n<=k  (-1)^i * C(m,i) * C(m-1+k-n*i,m-1);

容斥解法

  • 由于问题转化为将总和k为m份,每份的值xi>=0&&xi<=n-1的方案数。
  • 首先有经典组合公式:x1+x2+...+xm=k (xi>=0) 解的个数为C(k+m-1,m-1)。
  • 那么我们相用如上公式解决本题,发现上述公式没有此题中xi<=n-1的条件,那我们就求出总方案,容斥掉不合法的方案(即存在xi>=n-1)。
  • 对于有t个不合法的xi>=n(假设k>=t*n),我们怎么求这个不合法的方案数(即x1+x2+...+xm=k (存在xi>=n) 方案数),还是用经典组合公式,先做变换:如果xi=n) ==>  x1'+x2'+...+xm'=k-t*n (所有xi>=0);方案数就是C(k-t*n+m-1,m-1)。
  • 再进行容斥就是0个不合法 - 1个不合法 + 2个不合法 - 3个不合法。。。。
  • 公式如下:                                       容斥系数                  变量选法        c个不合法方案数
  • -> c个不合法( c>=0&&c*n<=k )        (-1)^c            *          C(m,c)     *     C(k-c*n+m-1,m-1)   

 

发现两种方法所得公式相同。

代码

#include 
using namespace std;
typedef long long ll;
const ll mod=998244353;
const ll M=2*1e5+5;
ll n,m,k;

ll fact[M],ifact[M];//fact[i]是i的阶乘,ifact[i]是阶乘的除法逆元,两者用于求组合数
ll pow_mod(ll n,ll k,ll mod)//快速幂求n^k余m的结果
{
    ll res=1;
    n=n%mod;
    while(k>0)
    {
        if(k&1)
            res=res*n%mod;
        n=n*n%mod;
        k>>=1;
    }
    return res;
}
void init()//初始化
{
    fact[0]=ifact[0]=1;
	for(int i=1;i0;i--)
        ifact[i-1]=ifact[i]*i%mod;
}

ll C(ll n,ll m)//求组合数
{
    if(n

 

 

 

你可能感兴趣的:(母函数,组合数学)