数的划分
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; }