简单的划分数

来源:互联网 发布:歼31和f35对比数据 编辑:程序博客网 时间:2024/05/16 23:55

问题

划分数就是将整数 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;}
1 0