找单词(母函数问题)
Description
假設有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 9Sample Output
7 379297 這類題也就能夠很明晰的做出來了,就兩個字“暴力” ,雖說這個詞不怎么招人喜歡,但是如何暴力,怎樣暴力確實一大知識點,DFS、BFS不都是暴力嗎,但還是很受歡迎,母函數就是一個有章可依,有模板可套的暴力。 1 #include<stdio.h> 2 #include<string.h> 3 4 int le[30],n1[55],n2[55]; 5 6 void GF( ) 7 { 8 memset(n1,0,sizeof(n1)); 9 memset(n2,0,sizeof(n2)); 10 n1[0]=1; //在上一篇報告里面講過其作用,可以說是一個入口 11 for(int i=1;i<=26;++i) 12 { 13 for(int j=0;j<=50;++j) 14 // j從0開始還是為了保留未參與合并的原值 15 for(int k=0;k<=le[i]&&k*i+j<=50;k++) 16 // k從0開始是為了保留n1[x]中原有的值,不至于在 17 // 后面n1[x]=n2[x]語句中出現n1[x]數據丟失。 18 n2[j+k*i]+=n1[j]; // 這和前面的判斷是否存在(只需賦值 為1)組合不同 19 for(int j=0;j<=50;++j) 20 { 21 n1[j]=n2[j]; // k從0開始保證了n1[x]只增不減 22 n2[j]=0; 23 } 24 } 25 } 26 27 int main() 28 { 29 int T; 30 scanf("%d",&T); 31 while(T--) 32 { 33 int cnt=0; 34 for(int i=1;i<=26;++i) 35 scanf("%d",&le[i]); 36 GF(); 37 for(int i=1;i<=50;++i) // 題目是要統計小于50的所有可能 38 cnt+=n1[i]; 39 printf("%d\n",cnt); 40 } 41 return 0; 42 }把 “Lvsi”開的初級母函數DIY 都做完了,由于中間看了背包,經常是腦袋里面一團混亂,尤其是HDU 1171,唉,又能用母函數,又能用多重背包。所以急忙寫點解題報告,清理清理下自己的思路。? 對母函數而言,在做題中,用到了它的兩種用法,一種可以說是原型的變形(簡化)。
其一:用來模擬組合問題,最經典莫過于 錢幣兌換 了,有1-N 種幣值的硬幣,如拿M元紙幣兌換,問有多少種兌換方式,母函數就是統計頻數(或其他變量)的啟發函數,其核心 語句 是 n1[j+k]+=n2[j];?
n1[x]--這個數組就是存儲頻數的,一般如果你換10元 這個數組在循環中的界值就為10,
n2[x]--這個是用來做臨時儲存用的,把一次合并操作中相同值的數加起來,且每次加的是n1[x](值暫不變)而不是加自身。
j--錢幣的組合值,n1[j] 就是組成 j 元錢的方案數。
k--這個就是當前參與組合的錢幣的動態值,比如一次操作中是將 6枚價值為10的硬幣組合進去,那么k<0.10...60>,在每次的操作中是這樣的,當k=0時,n2[j]=n1[j],這樣剛好能夠將n1[j]的原值過渡過來,當k=10時,n2[j+10]的值是在原來的基礎上在加上n1[j],因為這里的一枚價值為 10? 硬幣確實能夠和?已經能夠組合成的錢幣數 j? 組成 j+10的組合,而這種組合的的頻數N=P*1;P為原頻數?, P=n1[j]。而后的k取值則按照類似的關系進行。???
其二:用來枚舉所有可能的組合,不要求 求出頻數,只需統計是否可能存在,就像上一篇報告中遇到的題目,給你一定要求的錢幣只有價值為 1、2、5 的錢幣各若干枚,題中給出三個數代表各個錢幣的數量,問你用這些錢幣組合錢幣中從1開始,最小的不能組合成的錢幣數值。 因此此題中無需統計組合后某一數目值出現了多少次,統計也是多此一舉。其核心 語句為:
if(n1[j])???n2[j+k]=1;? 意思是說如果 前組合值值存在,那么當前組合值存在。
轉載于:https://www.cnblogs.com/wangmengmeng/p/4552565.html
總結
以上是生活随笔為你收集整理的找单词(母函数问题)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: paip.gui控件tabs控件加载内容
- 下一篇: android获取系统当前年月日时分秒的