数的划分

D14438. 【NOIP2001T】数的划分

时间限制1.0s   内存限制256.0MB  

输入文件名:div.in   输出文件名:div.out

试题来源:NOIP

问题描述

  将整数n分成k份,且每份不能为空,任意两份不能相同(不考虑顺序)。

  例如:n=7,k=3,下面三种分法被认为是相同的。

  1,1,5; 1,5,1; 5,1,1;

  问有多少种不同的分法。

输入格式

  输入:n,k (6<n<=200,2<=k<=6)

输出格式

  输出:一个整数,即不同的分法。

样例输入

7 3

 

样例输出

4

 

思路:

先努力尝试递归。

用n个数分成k份时

情况一:在第k份放下1份数,为了前k-1份都>1 ,前k-1份都+1,f(n,k)=f(n-k,k);

情况二:前k-1份中已有1,剩下n-1数,k-1份,f(n,k)= f(n-1,k-1);

如若数字小于份数自然分不下去了,相等时自然只有一种方法,k=1时也只有一种。

 

 

综上

f(n,k)= f(n-1,k-1) +f(n-k,k)

        1 (k=1||n=k&&n!=0)

        0 (n<k)

 

Code

递归:

#include<bits/stdc++.h>

 

using namespace std;

 

int n,k;

 

int dive(int num, int p){

               if (num < p) return 0;

               if ((num == p && num != 0) || p == 1) return 1;//边界

               return dive(num - 1, p - 1) + dive(num - p, p);

}

 

int main(){

               freopen("div.in","r",stdin);

               freopen("div.out","w",stdout);

               cin >> n >> k;

               int ans = dive(n,k);

               cout << ans << endl;

               return 0;

}

 

 

记忆化:

#include<bits/stdc++.h>

 

using namespace std;

 

int n,k;

int dp[210][10];

 

int dive(int num, int p){

               if (num < p) return 0;

               if ((num == p && num != 0) || p == 1) return 1;//边界

               if (dp[num][p]) return dp[num][p];

               return dp[num][p] = dive(num - 1, p - 1) + dive(num - p, p);

}

 

int main(){

               freopen("div.in","r",stdin);

               freopen("div.out","w",stdout);

               cin >> n >> k;

               int ans = dive(n,k);

               cout << ans << endl;

               return 0;

}

 

 

当然还可以递推求解:

Code:

递推:

#include<bits/stdc++.h>

 

using namespace std;

 

int n,k;

int ans[210][10];

 

int main(){

               freopen("div.in","r",stdin);

               freopen("div.out","w",stdout);

               cin >> n >> k;

               memset(ans,0,sizeof(ans));

               for (int i = 1; i <= n; i++)

                               ans[i][1] = 1;//边界

               for (int i = 1; i <= k; i++)

                               ans[i][i] = 1;//边界

               for (int i = 2; i <= k; i++)

                               for (int j = i; j <= n; j++)

                                              ans[j][i] = ans[j-1][i-1] + ans[j-i][i];

               cout << ans[n][k];

               cout << endl;

               return 0;

}

 

 

 

posted @ 2018-08-17 15:22  末裔  阅读(302)  评论(0编辑  收藏  举报