排列組合(HDU_1521) 指數型母函數

排列組合

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 3419    Accepted Submission(s): 1429


Problem Description
有n種物品,並且知道每種物品的數量。要求從中選出m件物品的排列數。例如有兩種物品A,B,並且數量都是1,從中選2件物品,則排列有"AB","BA"兩種。
 

Input
每組輸入數據有兩行,第一行是二個數n,m(1<=m,n<=10),表示物品數,第二行有n個數,分別表示這n件物品的數量。
 

Output
對應每組數據輸出排列數。(任何運算不會超出2^31的範圍)
 

Sample Input
2 2 1 1
 

Sample Output
2

 題目大意:求排列數。

解題思路:指數型母函數。


代碼如下:

#include"iostream"
#include"cstdio"
#include"cstring"
using namespace std;

const int maxn = 10;
double c1[maxn + 1], c2[maxn + 2];
double fac[maxn + 1];
int num[maxn + 1];

void MakeFac(){
    fac[0] = 1.0;
    for(int i = 1;i <= maxn;i ++)
        fac[i] = fac[i - 1] * i;
    
}

int min(int x, int y){
    return x < y ? x : y;
}

int main(){
    int n, m, t;
    MakeFac();
    while(scanf("%d%d", &n, &m) != EOF){
        memset(c1, 0, sizeof c1);
        memset(c2, 0, sizeof c2);
        for(int i = 1;i <= n;i ++){
            scanf("%d",&t);
            num[i] = min(t, m);
        }
        for(int j = 0;j <= num[1];j ++)
            c1[j] = 1.0/fac[j];
        for(int i = 2;i <= n;i ++){
            if(num[i] == 0) continue;
            for(int j = 0;j <= m;j ++)
                for(int k = 0;k <= num[i] && k + j <= m;k ++)
                    c2[k + j] += c1[j] / fac[k];
            for(int j = 0;j <= m;j ++){
                c1[j] = c2[j];
                c2[j] = 0;
            }
        }
        
        printf("%.0lf\n",c1[m]*fac[m]);
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章