放苹果
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 30894 | Accepted: 19504 |
Description
把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法。
Input
第一行是测试数据的数目t(0 <= t <= 20)。以下每行均包含二个整数M和N,以空格分开。1<=M,N<=10。
Output
对输入的每组数据M和N,用一行输出相应的K。
Sample Input
1 7 3
Sample Output
8
最基础的整数划分,求将n拆分成不超过m个数之和的方法数
递归法:
根据n和m的关系,考虑以下几种情况:
(1)当n=1时,不论m的值为多少(m>0),只有一种划分即{1};
(2) 当m=1时,不论n的值为多少,只有一种划分即n个1,{1,1,1,...,1};
(3) 当n=m时,根据划分中是否包含n,可以分为两种情况:
(a). 划分中包含n的情况,只有一个即{n};
(b). 划分中不包含n的情况,这时划分中最大的数字也一定比n小,即n的所有(n-1)划分。
因此 f(n,n) =1 + f(n,n-1);
(4) 当n<m时,由于划分中不可能出现负数,因此就相当于f(n,n);
(5) 但n>m时,根据划分中是否包含最大值m,可以分为两种情况:
(a). 划分中包含m的情况,即{m, {x1,x2,...xi}}, 其中{x1,x2,... xi} 的和为n-m,因此这种情况下
为f(n-m,m)
(b). 划分中不包含m的情况,则划分中所有值都比m小,即n的(m-1)划分,个数为f(n,m-1);
因此 f(n, m) = f(n-m, m)+f(n,m-1);
综上所述:
f(n, m)= 1; (n=1 or m=1)
f(n, n); (n<m)
1+ f(n, m-1); (n=m)
f(n-m,m)+f(n,m-1); (n>m)
1 //2016.9.1 2 #include <iostream> 3 #include <cstdio> 4 #define N 15 5 6 using namespace std; 7 8 int f(int n, int m) 9 { 10 if(n==1 || m==1)return 1; 11 else if(n < m)return f(n, n); 12 else if(n == m)return (1+f(n, n-1)); 13 else return f(n-m, m)+f(n, m-1); 14 } 15 16 int main() 17 { 18 int T, n, m; 19 cin>>T; 20 while(T--) 21 { 22 scanf("%d%d", &n, &m); 23 int ans = f(n, m); 24 cout<<ans<<endl; 25 } 26 27 return 0; 28 }