日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

3.1 普通型生成函数

發布時間:2025/4/9 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 3.1 普通型生成函数 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?母函數(生成函數):? ?

??? 生成函數有普通型生成函數和指數型生成函數兩種。

??? 形式上,普通型母函數用于解決多重集的組合問題,

??????????????? 指數型母函數用于解決多重集的排列問題。

??? 母函數還可以解決遞歸數列的通項問題(例如使用母函數解決斐波那契數列,Catalan數的通項公式)。

普通母函數:

??? 構造母函數G(x), G(x) = a0 + a1*x + a2*?+ a3*?+....+ an*,? 則稱G(x)是數列a0,a1…an的母函數。

??? 通常普通母函數用來解多重集的組合問題,其思想就是構造一個函數來解決問題,一般過程如下:

??? 1.建立模型:物品n種,每種數量分別為k1,k2,..kn個,每種物品又有一個屬性值p1,p2,…pn,(如本題的字母價值),

????? 求屬性值為m的物品組合方法數。(若數量ki無窮 也成立,即對應下面式子中第ki項的指數一直到無窮)

??? 2.構造母函數:G(x)=(1++…)(1+++…)…(1+++…)??????? (一)

??????????????????????????????? =a0 + a1*x + a2*?+ a3*?+....+ akk*???? (設kk=k1·p1+k2·p2+…kn·pn)? (二)

????????????????? G(x)含義: ak 為屬性值為k的組合方法數。

母函數利用的思想:

??? 1.把組合問題的加法法則和冪級數的乘冪對應起來。

??? 2.把離散數列和冪級數對應起來,把離散數列間的相互結合關系對應成為冪級數間的運算關系,最后由冪級數形式來

?????? 確定離散數列的構造。

代碼實現:

??? 求G(x)時一項一項累乘。先令G=1=(1+0*x+0*+…0*),再令G=G*(1++…)得到形式(二)的式子…最后令G=G*(1+++…)。

模板:

const int MAX_N = 10000; int a[MAX_N]; // 保存函數的各項系數 int b[MAX_N]; // 中間量, 保存每一次的情況 int NumMin[MAX_N]; //每種最少數量 int NumMax[MAX_N]; //每種最多數量 int Val[MAX_N]; //每種的權重 int N; // 種數 int P; // 價值上限(即目標); memset(a, 0, sizeof(a)); memset(b, 0, sizeof(b)); a[0] = 1; for (int i = 1; i <= N; i++) { // 循環每種函數(1 + a1 x ^ p1 + a2 x ^ p2 + ......) // 一般情況下NumMin 都是 0// 如果每種情況都可以取無限個 就可以刪去 j <= NumMAX[i] for (int j = NumMin[i]; j <= NumMax[i] && j * Val[i] <= P; j++)// 兩個函數相乘 k 是被乘函數各項的指數 for (int k = 0; k + j * Val[i] <= P; k++)// k + j * Val[i] 是結果函數的指數 b[k + j * Val[i]] += a[k];for (int j = 0; j <= P; j++) {a[j] = b[j];b[j] = 0; } }

優化:?

  當數據規模特別大時,可以用一個 last 來標記目前最大的指數,這樣只需要在 0 ~ last 上計算。

a[0] = 1; int last = 0; //因為有 last ,所以無需初始化其他位 for (int i = 0; i < N; i++) {int lastnext = min(last + NumMax[i]* Val[i], P); memset(b, 0, sizeof(lastnext + 1));for (int j = NumMin[i]; j <= NumMax[i] && j * Val[i] <= lastnext; j++)for (int k = 0; k + j * Val[i] <= lastnext; k++)b[k + j * Val[i]] += a[k];for (int j = 0; j <= P; j++) {a[j] = b[j];b[j] = 0; }last = lastnext; }

// 這種方式應該不適用于無限個的情況

例題:

?

Problem 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 9 Sample Output 7 379297

?

題解:

1.建模:物品(字母)26種,每種數量x1,x2…x26,屬性值為1,2,3..26,求屬性值和<=50的組合方法數。

2.G(x)=(1++…)(1+++…)…(1++…)

#include<iostream> #include<cstdio> #include<cstring> using namespace std; long long a[60],b[60];int main() {int n;cin>>n;while(n--){memset(a,0,sizeof(a));memset(b,0,sizeof(b));a[0]=1;int x;for(int i=1;i<=26;i++){scanf("%d",&x);for(int j=0;j<=50;j++){for(int k=0;k<=x&&(j+k*i<=50);k++){b[j+k*i]+=a[j];}}for(int j=0;j<=50;j++){a[j]=b[j];b[j]=0;}}long long ans=0;for(int i=1;i<=50;i++)ans+=a[i];cout<<ans<<endl;} } AC Code

?


?

轉載于:https://www.cnblogs.com/astonc/p/9916159.html

《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

總結

以上是生活随笔為你收集整理的3.1 普通型生成函数的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。