母函式入門練習
阿新 • • 發佈:2018-11-20
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; } } }