1. 程式人生 > >母函式入門練習

母函式入門練習

HDU2082

假設有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認為是同一個單詞)。

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

解第一組的情況:第一組結果為7種 可列方程:G(x) =(1+1*x^1)*(1+1*x^2)*(1+1*x^3)=1+x+x^2+2*x^3+x^4+x^5+x^6;

組合的種數共:1+1+2+1+1+1=7  (減去x^0這一項,因為組成一個單詞不可能什麼字母都不取)

1+1*x^2 表示 價值2的字母B有1個(即係數1) 1+1*x^2=1*x^0+1*x^2

若需解第二組亦可用同樣的方法(母函式)解答。

g(x)=(1+x^1+x^2+...x^9)*(1+x^2+x^4)*(1+x^3+x^6+...+x^18)*……

 

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int a[27];//ct為臨時陣列,c為結果陣列
int c[55],ct[55];//兩個陣列的下標代表項的指數,值代表項的係數(價值的大小,選法的種數)
int main()
{
  //  freopen("datain.txt","r",stdin);
    int n;
    while(~scanf("%d",&n)){
        if(!n)break;
        while(n--){
            for(int i=1;i<=26;i++){
                cin>>a[i];//每個字母的個數
            }
            memset(c,0,sizeof(c));
            memset(ct,0,sizeof(ct));
            for(int i=0;i<=50&&i<=a[1];i++)
                c[i]=1;//每個價值,只拿A的情況都是1
            for(int i=2;i<=26;i++){//i表示第i個字母(即第i個多項式)
                for(int j=0;j<=50;j++){ 
    //j表示前面i-1個多項式累乘後的結果多項式裡的第j項,即價值j
                    for(int k=0;k+j<=50&&k<=a[i]*i;k+=i){
    // k是第i個多項式中 可取字母的價值,公差為i 從0到a[i]*i
                       ct[j+k]+=c[j];
    //將第i個多項式的每一項,與結果多項式的第j項進行冪運算
                    }
                }
                for(int i=0;i<=50;i++){
                    c[i]=ct[i];//將臨時陣列的值賦給答案陣列
                    ct[i]=0;//臨時陣列歸零,準備計算下一個多項式
                }
            }
            int sum=-1;//sum初始-1,減去一種最後指數為0即什麼字母都不取的情況
            for(int i=0;i<=50;i++)
                sum+=c[i];//將答案陣列的0到50項求和
            cout<<sum<<endl;
        }
    }
}