簡單的劃分數

問題

劃分數就是將整數 n 分成若干個大於 0 的數的和。例如,n = 4,可以分成 1+1+1+1,1+1+2,1+3,2+2,4,一共 5 種方案,注意 1+1+2,1+2+1,2+1+1被認爲是相同的方案。

求整數 80 的劃分數方案。


答案

15796476


思路

還是用dfs做,只是有點慢(要25s)( ̄▽ ̄)”(只適合小數,如果是大數的話就很慢了)。

也可以用遞歸做,將遞歸函數的聲明爲 int d(int n, int m);其中n爲要劃分的正整數,m是劃分中的最大加數(當m > n時,最大加數爲n),分下列幾種情況:

  • 當 n=1,d爲1,因爲無論m爲多少就只有1
  • 當 m=1 時,d=1 ,由上例可知,當 n=4 時,d只有 1+1+1+1 這1種
  • 當 n=m 時,又分爲兩種情況:

    • 第一種就是包含m的時候,就只有 m 這一種。
    • 另外一種就是不包含 m ,那麼最大數就爲 m-1 ,有 d(n,m-1) 種

    因此當 n=m 時,d(n , n)=1+ d(n,n-1)

  • 當n < m 就相當於 d(n,n) 了

  • 當 n > m 時,一種是不含m,爲d(n,m-1)種,一種是含有m,有d(n-m,m)種

    因此d(n,m)=d(n-m,m)+d(n,m-1)

    注意理解d(n-m,m),注意這裏的前提是劃分包含m,所以將m提出來一個,保證劃分中一定會有m,剩下數字劃分的和爲n-m,而這n-m中可能不會出現m,也可能出現m,但由於我們已經提出了一個m,所以此處不用擔心m是否再出現。第一個數爲什麼是(n-m),原因是提出一個m後,已經保證了劃分中一定出現m,而n-m還沒有進行劃分,這裏忽略提出的m,對剩下的整數n-m進行劃分,劃分的最大值仍然是m


代碼

  • dfs代碼
#include <iostream>
using namespace std;
int total=0;
void dfs(int a,int sum){
    if (sum==80) {
        total++;
        return;
    }
    if (sum>80) {
        return;
    }
    for (int i=a;i<=80;i++) {
        dfs(i,sum+i);
    }
}
int main(int argc, char *argv[]) {
    dfs(1,0);
    printf("%d",total);
    return 0;
}
  • 遞歸代碼
#include <stdio.h> 
int d(int n, int m){
    if(n < 1 || m < 1) return 0;
    if(n == 1 || m == 1) return 1;
    if(n < m) return d(n, n);
    if(n == m) return (d(n, m - 1) + 1);
    if(n > m) return d(n, m - 1)+d((n - m), m);
}
int main(){
    printf("%d",d(80,80));
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章