1. 程式人生 > >HDU_2082 找單詞 【母函式的應用】

HDU_2082 找單詞 【母函式的應用】

題目:

假設有x1個字母A, x2個字母B,..... x26個字母Z,同時假設字母A的價值為1,字母B的價值為2,..... 字母Z的價值為26。那麼,對於給定的字母,可以找到多少價值<=50的單詞呢?單詞的價值就是組成一個單詞的所有字母的價值之和,比如,單詞ACM的價值是1+3+14=18,單詞HDU的價值是8+4+21=33。(組成的單詞與排列順序無關,比如ACM與CMA認為是同一個單詞)。  Input輸入首先是一個整數N,代表測試例項的個數。 
然後包括N行資料,每行包括26個<=20的整數x1,x2,.....x26. 

Output對於每個測試例項,請輸出能找到的總價值<=50的單詞數,每個例項的輸出佔一行。Sample Input
2
1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
9 2 6 2 10 2 2 5 6 1 0 2 7 0 2 2 7 5 10 6 10 2 10 6 1 9
Sample Output
7
379297
題意分析: 看見組合,還是求很多種元素的組合數,那麼我們可以想到的就是運用母函數了。 但這題需要注意的就是,他的每個字母是有不同的價值的,相當於湊重量時,不同砝碼的重量。所以最後利用母函式的模板,求解即可。 f(x) = (1+x^{k_{1}*a}+x^{k_{2}*a}+\cdots )*(1+x^{k_{1}*b}+x^{k_{2}*b}+\cdots )* (1+x^{k_{1}*c}+x^{k_{2}*c}+\cdots ) k序列就是{1,2,3,...}表示的是有幾個該字母。a,b,c,...表示的是對應的值。
AC程式碼:
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;

int Cnt[60], Cnt2[60];

int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        int N;
        long long ans = 0;
        memset(Cnt, 0, sizeof(Cnt));
        memset(Cnt2, 0, sizeof(Cnt2));
        Cnt[0] = 1;
        for(int i = 1; i <= 26; i++)
        {
            scanf("%d", &N);
            for(int j = 0; j <= 50; j++)   //前面的係數
            {
                for(int k = 0; k <= N && j+k*i <= 50; k++)
                {
                    Cnt2[j+k*i] += Cnt[j];
                }
            }
            for(int j = 0; j <= 50; j++)
            {
                Cnt[j] = Cnt2[j];
                Cnt2[j] = 0;
            }
        }
        for(int i = 1; i <= 50; i++)
        {
            ans += Cnt[i];
        }
        printf("%I64d\n", ans);
    }
    return 0;
}