M

有n种物品,并且知道每种物品的数量。要求从中选出m件物品的排列数。例如有两种物品A,B,并且数量都是1,从中选2件物品,则排列有"AB","BA"两种。

每组输入数据有两行,第一行是二个数n,m(1<=m,n<=10),表示物品数,第二行有n个数,分别表示这n件物品的数量。

对应每组数据输出排列数。(任何运算不会超出2^31的范围)

input
2 2
1 1
output
2

超级水
我们直接暴力枚举每种物品选几个,记为(b_i)
每种枚举方案的贡献为
(Ans = m! / (phi_{i = 1}^{n} b_i!))

求和即可


#include<iostream>
#include<cstdio>

using namespace std;

#define int long long

int fac[50];

int n,m;
int a[20];

int b[20];
int ans;

void dfs(int st,int s){
    if(st == n + 1){
        if(s != m) return ;
        int t = fac[m];
        
        for(int i =  1; i <= n; ++ i) 
        if(b[i] > 0) t /= fac[b[i]];
        
        ans += t;
        
        return ;
    }
    
    for(int i = 0; i <= m - s && i <= a[st]; ++ i){
        b[st] = i;
        dfs(st + 1, s + i);
    }
}

signed main(){
    fac[0] = 1;
    for(int i = 1; i <= 12; ++ i) fac[i] = fac[i - 1] * i;
    
    while (scanf("%lld%lld",&n,&m)!= EOF){
    ans = 0;
    for(int i = 1; i <= n; ++ i) scanf("%lld",&a[i]);

    dfs(1,0);
    
    printf("%lld
",ans);
    }
    return 0;
}


原文地址:https://www.cnblogs.com/zzhzzh123/p/13343789.html