整數拆分的兩種解法(已完成)

2021-06-09 22:07:35 字數 1644 閱讀 8528

前幾天在演算法書上看到乙個整數拆分的題目,覺得挺有意思,記錄如下:

例如:n==6有 6

5+14+2    4+1+1

3+3    3+2+1     3+1+1+1

2+2+2     2+2+1+1        2+1+1+1+1

1+1+1+1+1+1

共11種分解方法,所以輸出應該為11。

拆分按照因子從大到小排列,每一次拆分都可視為問題規模的減少,所以可以使用遞迴解決。

設q(n,m)為整數n使用不大於m的整數進行拆分的所有情況總數,因此有

1)當n==m時

可以分為兩種情況,乙個是使用n本身,只有一種情況。二個是使用不大於n-1的整數進行拆分。

所以此時q(n,m)=1+q(n,n-1);

2)當n

使用比n大的數進行拆分沒有意義,所以此時q(n,m)=q(n,n)

3)當n>m時

這時候有兩種情況,乙個是使用m對n進行拆分,乙個是使用小於m的數對n進行拆分

對於第乙個,使用m對n進行拆分,所以拆分出來的情況最大的數是m,剩下的所有數加起來為n-m,問題變成使用不大於m的整數對n-m進行拆分,所以此時為q(n-m,m)

對於第二個,使用小於m的數對n進行拆分,表示為q(n,m-1)

4)當n==1或者m==1時 只有一種情況,返回1。注意,這裡可能會漏掉m==1的情況,實際上這種情況是存在的。

所以可以使用遞迴函式程式設計如下:

#include #include using namespace std;

int q(int n,int m)

if(nm)

return q(n,m-1)+q(n-m,m);

}void main()

}

使用母函式法

整數分解用母函式可以這樣理解,分別用任意個1,2,3,4,……,n可以加起來可以表示成n的種數。又因為當使用整數m對n進行分解時,所使用的次數不能多於n/m次,所以可以寫下母函式如下:

g(x)=(1+x^1+x^2+……+x^n)*(1+x^2+x^4+……+x^((n/2)*2))*……

*(1+x^m+x^(2*m)+x^(3*m)+……+x^((n/m)*m))*……*(1+x^n)

在程式中使用set陣列表示每一輪乘法後得到係數,c陣列表示到現在為止乘法得到的係數總和。最後算出結果後x^n對應的係數則為可分解的可能數。**如下:

#includeconst int num=1000;

int set[num];

int c[num];

void init()

if(n==1)

else if(m==1){

//當m為1,意味著要輸出n個m相加

for(int i=0; im){

//如果n大於m,使用m作為分解,則要首先輸出m+的形式

printf("%d+",m);

//記錄下作為樹幹節點m的值並使i自增

set[i++]=m;

//遞迴輸出m+以後的分解

q(n-m,m,i);

//遞迴完畢後需要將陣列記錄後退乙個,回到上乙個節點,如上圖示過程2

i--;

//執行另乙個分支,在下一次遞迴之前輸出記錄的資料,如上圖示過程3

for(int j=0; j

整數拆分的兩種解法(已完成)

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!分類 演算法 2012 09 30 17 04 263人閱讀收藏 舉報目錄 題目 給定乙個整數n,輸出這個整數拆分的可能總數 分析一分析二 題目二 給定乙個整數n,輸出這個整數拆分的可能形式 即輸出全部情況 前幾天在演算法書上看到乙個整數拆分的題目...

nyoj90 整數拆分(遞迴,揹包兩種解法)

題目 把乙個整數拆分成的所有情況。遞迴 include includeusing namespace std int z 11 int zh int n,int m 最近在做動態規劃的時候發現這個題目也可以用揹包來些,並且比用遞迴喜惡簡單的多。效率也高很多。動態轉移方程 dp i dp i dp i...

Bacon Number 兩種解法

view code 題目 cid 567 題目分析 與longth way 類似 這個好象就是傳說中的六度人脈,你只要通過六度人脈就可以找到世界上的任何乙個人。假設乙個人一生會認識n個人,那n n 1 n 2 n 3 n 4 n 5 n 6 世界總人數。給定一些邊確定乙個圖,即給定一些點之間的連通情...