[组合数学]给定每种数字的个数计算不包含前导0的数的个数

这个问题源于昨日的 CF E题。让我想了好久.

问题定义

给定每种数字( 0 , 1 , 2 , 3 , , 9 )的个数 c i : i c i ,问用完其中每种数字,组合成一个数,其中不包含前导0的数有多少个。

比如:

c = { 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } , 那他可以组合成:

120,102,210,201

解法1

如果包含前导0也算进去,那么就是一个简单的多重排列问题了, a n s = ( i = 0 9 c [ i ] ) ! c [ i ] !

同理我们可以先把不包含0的排列数算出来 : r e t = ( i = 1 9 c [ i ] ) ! i = 1 9 c [ i ] ! , 对于其中每个排列,设 n = i = 1 9 c [ i ] 仅需将 后面的 n 1 个数和 0排列就好, t = ( c [ 0 ] + n 1 ) ! c [ 0 ] ! ( n 1 ) !

所以最终解为:

a n s = r e t t = ( i = 1 9 c [ i ] ) ! i = 1 9 c [ i ] ! ( c [ 0 ] + n 1 ) ! c [ 0 ] ! ( n 1 ) !

解法2

解法2有点麻烦,就是可以直接计算包含0的情况,然后枚举所有前导0的个数,减去就好。

代码

 LL cal_cnt(int *state){
    LL n=0;
    for(int i=1 ; i<10 ; ++i)n += state[i];
    LL ret = fact[n];
    for(int i=1 ; i<10 ; ++i)ret /=fact[state[i]];
    LL tmp =1;
    if(cnt[0]>0){
        tmp = fact[n+state[0]-1]/fact[state[0]]/fact[n-1];
    }
    return ret*tmp;
}

猜你喜欢

转载自blog.csdn.net/dylan_frank/article/details/80792328