关于整数划分的问题
? ?(一)遞歸法? ? ? ? ? ? ? ? ? ? ??
?????? 根據(jù)n和m的關(guān)系,考慮以下幾種情況:?
???????(1)當(dāng)n=1時(shí),不論m的值為多少(m>0),只有一種劃分即{1};
??????? (2)? 當(dāng)m=1時(shí),不論n的值為多少,只有一種劃分即n個(gè)1,{1,1,1,...,1};
??????? (3)? 當(dāng)n=m時(shí),根據(jù)劃分中是否包含n,可以分為兩種情況:
????????????? (a). 劃分中包含n的情況,只有一個(gè)即{n};
????????????? (b). 劃分中不包含n的情況,這時(shí)劃分中最大的數(shù)字也一定比n小,即n的所有(n-1)劃分。
????????????? 因此 f(n,n) =1 + f(n,n-1);
??????? (4) 當(dāng)n<m時(shí),由于劃分中不可能出現(xiàn)負(fù)數(shù),因此就相當(dāng)于f(n,n);
??????? (5) 但n>m時(shí),根據(jù)劃分中是否包含最大值m,可以分為兩種情況:
?????????????? (a). 劃分中包含m的情況,即{m, {x1,x2,...xi}}, 其中{x1,x2,... xi}?的和為n-m,可能再次出現(xiàn)m,因此是(n-m)的m劃分,因此這種劃分
???????????????????? 個(gè)數(shù)為f(n-m, m);
?????????????? (b). 劃分中不包含m的情況,則劃分中所有值都比m小,即n的(m-1)劃分,個(gè)數(shù)為f(n,m-1);
????????????? 因此 f(n, m) = f(n-m, m)+f(n,m-1);
? 綜合以上情況,我們可以看出,上面的結(jié)論具有遞歸定義特征,其中(1)和(2)屬于回歸條件,(3)和(4)屬于特殊情況,將會(huì)轉(zhuǎn)換為情況(5)。而情況(5)為通用情況,屬于遞推的方法,其本質(zhì)主要是通過(guò)減小m以達(dá)到回歸條件,從而解決問(wèn)題。其遞推表達(dá)式如下:
? ? ? ? ? ? ? ? ? ? ? ? ? ?f(n, m)= ?1; ? ? ? ? ? ? ? ?(n=1 or m=1)
??????????????????????????? f(n, n);???????????????????????? (n<m)
??????????????????????????? 1+ f(n, m-1);??????????????? (n=m)
??????????????????????????? f(n-m,m)+f(n,m-1);????? ?(n>m)
?代碼:
1 #include<stdio.h> 2 int div(int n,int m) 3 { 4 if (n < m) 5 return div(n,n); 6 else if (n==1||m==1) 7 return 1; 8 else if (n==m) 9 return 1 + div(n,m-1); 10 else 11 { 12 return div(n,m-1) + div(n-m,m); 13 } 14 } 15 int main() 16 { 17 int n,m,t; 18 scanf("%d",&t); 19 while(t--) 20 { 21 scanf("%d%d",&n,&m); 22 printf("%d\n",div(n,m)); 23 } 24 return 0; 25 26 } View Code(二)母函數(shù)法
? 則對(duì)于從1到N的所有可能組合結(jié)果我們可以表示為:
???????? G(x) = (1+x+x^2+x^3+...+x^n) (1+x^2+x^4+...) (1+x^3+x^6+...) ... (1+x^n)
???????????????? = g(x,1) g(x,2) g(x,3) ... g(x, n)
???????????????? = a0 + a1* x + a2* x^2 + ... + an* x^n + ... ;? (展開式)
????????上面的表達(dá)式中,每一個(gè)括號(hào)內(nèi)的多項(xiàng)式代表了數(shù)字i的參與到劃分中的所有可能情況。因此該多項(xiàng)式展開后,由于x^a * x^b=x^(a+b),因此 x^i 就代表了i的劃分,展開后(x^i)項(xiàng)的系數(shù)也就是i的所有劃分的個(gè)數(shù),即f(n,n)=an (上式中g(shù)(x,i)表示數(shù)字i的所有可能出現(xiàn)情況)。
??????? 由此我們找到了關(guān)于整數(shù)劃分的母函數(shù)G(x);剩下的問(wèn)題是,我們需要求出G(x)的展開后的所有系數(shù)。
??????? 為此我們首先要做多項(xiàng)式乘法,對(duì)于我們來(lái)說(shuō)并不困難。我們把一個(gè)關(guān)于x的一元多項(xiàng)式用一個(gè)整數(shù)數(shù)組a[]表示,a[i]代表x^i的系數(shù),即:
??????? g(x) = a[0] + a[1]x + a[2]x^2 + ... + a[n]x^n;
1 多項(xiàng)式相乘,即c=a*b 2 3 #define N 130 4 5 unsigned long a[N];/*多項(xiàng)式a的系數(shù)數(shù)組*/ 6 7 unsigned long b[N];/*多項(xiàng)式b的系數(shù)數(shù)組*/ 8 9 unsigned long c[N];/*存儲(chǔ)多項(xiàng)式a*b的結(jié)果*/ 10 11 12 13 /*兩個(gè)多項(xiàng)式進(jìn)行乘法,系數(shù)分別在a和b中,結(jié)果保存到c ,項(xiàng)最大次數(shù)到N */ 14 15 /*注意這里我們只需要計(jì)算到前N項(xiàng)就夠了。*/ 16 17 void Poly() 18 19 { 20 21 int i,j; 22 23 memset(c,0,sizeof(c)); 24 25 for(i=0; i<N; i++) 26 27 for(j=0; j<N-i; j++) /*y<N-i: 確保i+j不會(huì)越界*/ 28 29 c[i+j] += a[i]*b[j]; 30 31 } View Code 1 計(jì)算G(x)的前N項(xiàng)系數(shù) 2 3 /*計(jì)算出前N項(xiàng)系數(shù)!即g(x,1) g(x,2)... g(x,n)的展開結(jié)果*/ 4 5 void Init() 6 7 { 8 9 int i,k; 10 11 memset(a,0,sizeof(a)); 12 13 memset(c,0,sizeof(c)); 14 15 for(i=0;i<N;i++) a[i]=1; /*第一個(gè)多項(xiàng)式:g(x, 1) = x^0 + x^1 + x^2 + x^3 + */ 16 17 for(k=2;k<N;k++) 18 19 { 20 21 memset(b,0,sizeof(b)); 22 23 for(i=0;i<N;i+=k) b[i]=1;/*第k個(gè)多項(xiàng)式:g(x, k) = x^0 + x^(k) + x^(2k) + x^(3k) + */ 24 25 Poly(); /* 多項(xiàng)式乘法:c= a*b */ 26 27 memcpy(a,c,sizeof(c)); /*把相乘的結(jié)果從c復(fù)制到a中:c=a; */ 28 29 } 30 31 } View Code?通過(guò)以上的代碼,我們就計(jì)算出了G(x)的展開后的結(jié)果,保存到數(shù)組c中。此時(shí)有:f(n,n)=c[n];剩下的工作只是把相應(yīng)的數(shù)組元素輸出。
轉(zhuǎn)載于:https://www.cnblogs.com/lahblogs/articles/3261540.html
總結(jié)
- 上一篇: 鸟哥的Linux私房菜知识点总结(持续更
- 下一篇: 基于FPGA的图像处理(一)--Syst