整數的拆分2

2021-06-29 04:30:07 字數 2769 閱讀 9525

方法二——母函式

下面我們從另乙個角度,即「母函式

」的角度來考慮這個問題。

所謂母函式,即為關於x的乙個多項式g(x):

有g(x) = a0 + a1*x + a2*x^2 + a3*x^3 + ......

則我們稱g(x)為序列(a0, a1, a2,.....)的母函式。關於母函式的思路我們不做更過分析。

我們從整數劃分考慮,假設n的某個劃分中,1的出現個數記為a1,2的個數記為a2,.....,i的個數記為ai,

顯然有:ak <= n/k(0<= k <=n)

因此n的劃分數f(n,n),也就是從1到n這n個數字抽取這樣的組合,每個數字理論上可以無限重複出現,即個數隨意,使它們的綜合為n。顯然,數字i可以有如下可能,出現0次(即不出現

),1次,2次,......,k次等等。把數字i用(x^i)表示,出現k次的數字i用(x^(i*k)

)表示,不出現用1表示。

例如,數字2用x^2表示,2個2用x^4表示,3個2用x^6表示,k個2用x^2k表示。

則對於從1到n的所有可能組合結果我們可以表示為:

g(x) = ( 1 + x + x^2 + x^3 + ... + x^n)*(1 + x^2 + x^4 + 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 + ....//展開式

上面的表示式中,每個括號內的多項式代表了數字i的參與到劃分中的所有可能情況。因此,該多項式展開後,由於x^a *x^b = x^(a+b),因此x^i就代表了i的劃分,展開後(x^i

)項的係數也就是i的所有劃分個數,即f(n,n) = an。

由此我們找到了關於整數劃分的母函式g(x);剩下的問題就是,我們需要求出g(x)的展開後的所有係數。

為此,我們首先要做多項式乘法,對於我們來說,並不困難。我們把乙個關於x的多項式用乙個整數陣列a表示,a[i]代表x^i的係數,即:

g(x) = a[0] + a[1]x + a[2]x^2 + ... + a[n]x^n;

則關於多項式乘法的**如下,其中陣列a和陣列b表示兩個要相乘的多項式,結果儲存到陣列c中。

#include #include #include //母函式法求整數劃分

#define maxnum 100 //最高次數

unsigned long a[maxnum];

unsigned long b[maxnum];

unsigned long c[maxnum]; //儲存結果

//兩個多項式進行乘法,係數分別儲存在a和b中,結果儲存到c,項的最大次數到maxnum

void poly()

}}//計算前n項的係數,即g(x,1)*g(x,2)*....*g(x,n)的展開結果

void init(int m)

//for(j = 2; j <= maxnum; j++)//只能求f(n,n)

//通過修改這裡,使得可以求f(n,m),對於任意的正整數n,m都適合

for(j = 2; j <= m; j++)

//多項式相乘:c = a * b

poly();

//將結果c儲存到a中

memcpy(a, c, sizeof(c));

}}//母函式方法得出整數劃分相應的劃分數目

//n:整數

//m:劃分方法

void calprint(int n, int m)

else

}int main(int argc, char **argv)

if(m <= 0)

printf("母函式法");

calprint(n,m);

return 0;

}

改進:現在要求整數只能拆分成1,2,4,10,20,40,100,200,400,1000,2000這11個數

母函式法求解整數劃分

#include #include #include //母函式法求整數劃分

#define maxnum 6001 //最高次數

unsigned long a[maxnum];

unsigned long b[maxnum];

unsigned long c[maxnum]; //儲存結果

int d = ;

//兩個多項式進行乘法,係數分別儲存在a和b中,結果儲存到c,項的最大次數到maxnum

void poly()

}}//計算前n項的係數,即g(x,1)*g(x,2)*....*g(x,n)的展開結果

void init(int m)

//for(j = 2; j <= maxnum; j++)//只能求f(n,n)

//通過修改這裡,使得可以求f(n,m),對於任意的正整數n,m都適合

for(j = 1; j <= m; j++)

//多項式相乘:c = a * b

poly();

//將結果c儲存到a中

memcpy(a, c, sizeof(c));

}}int main(int argc, char **argv)

init(m);

printf("母函式法");

printf("整數劃分(%d)方法數目為%ld\n",n,c[n]);

return 0;

}

整數的拆分

母函式將問題轉換為關於母函式的某種代數問題甚至變成關於母函式的某種形式的運算,以整數拆分為例.所謂的整數拆分,即將正整數n分解成 若干正整數的和,不考慮其求和的順序,一般假定 n n 1 n 2 cdots n k,n 1 geq n 2 geq n 3 geq cdots geq n k 而且分解...

整數的拆分

引自 華師大oj 1009 問題描述 將正整數n表示成一系列正整數之和 n n1 n2 nk,其中n1 n2 nk 1,k 1。正整數n的這種表示稱為正整數n的劃分。求正整數n的不 同劃分個數。例如正整數6有如下11種不同的劃分 6 5 1 4 2,4 1 1 3 3,3 2 1,3 1 1 1 2...

整數的拆分

整數拆分分為有序拆分和無序拆分 有序拆分 把n拆分為 r個數,就相當於把n個球用 r 1塊隔板插入到n 1個空隙裡 c r 1,n 1 放球模型,把n個無區別的球放入到r個有區別的盒子裡,每個盒子至少乙個。無序拆分 把n拆分為 r個數,把n個相同的球放入到r個相同的盒子裡,允許盒子為空。把n個相同的...