题目来源:http://ybt.ssoier.cn:8088/problem_show.php?pid=1222
1222:放苹果
时间限制: 1000 ms 内存限制: 65536 KB
提交数: 2382 通过数: 1636
【题目描述】
把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法。
【输入】
第一行是测试数据的数目t(0 ≤ t ≤ 20)。以下每行均包含二个整数M和N,以空格分开。1≤M,N≤10。
【输出】
对输入的每组数据M和N,用一行输出相应的K。
【输入样例】
1 7 3
【输出样例】
8
解析:
数学意义上讲,这道题属于整数划分。
引自百度:
指把一个正整数n写成多个大于等于1且小于等于其本身的整数的和,则其中各加数所构成的集合为n的一个划分。这是一个典型的递归算法。
所谓整数划分,是指把一个正整数n写成为
其中, 为正整数,并且
;
为n的一个划分。如果
中的最大值不超过m,即
,则称它属于n的一个m划分。
解法:
这里我们记n的m划分的个数为 。例如,当n=4时,有5个划分,即
,
,
,
,
。
注意: 和
被认为是同一个划分。
根据n和m的关系,考虑一下几种情况:
(一)当 时,无论m的值为多少
,只有一种划分,即
。
(二)当 时,无论n的值为多少,只有一种划分,即n个1,
。
(三)当 时,根据划分中是否包含n,可以分为以下两种情况:
(1)划分中包含n的情况,只有一个,即 。
(2)划分中不包含n的情况,这时划分中最大的数字也一定比n小,即n的所有 划分。因此 。
(四)当 时,由于划分中不可能出现负数,因此就相当于
。
(五)当 时,根据划分中是否包含最大值m,可以分为以下两种情况:
(1)划分中包含m的情况,即 ,其中
的和为n-m,因此这种情况下为
。
(2)划分中不包含m的情况,则划分中所有值都比m小,即n的 划分,个数为
。因此
。
emmmmm....
这就是递归式。
参考代码:
1 #include<cstdio> 2 #include<cmath> 3 #include<iostream> 4 #include<cstring> 5 using namespace std; 6 int n,k; 7 int dfs(int a,int p) 8 { 9 //这里很巧妙,找到了当苹果为0时作递归边界 10 if(a==0) return 1;//若没有苹果时,只有一种分法 11 if(p==1) return 1;//只有一个盘子,也是仅一种分法 12 if(a<p) return dfs(a,a);//尽可能压缩计算量,盘子数多于苹果数并无意义 13 return dfs(a,p-1)+dfs(a-p,p); 14 } 15 int main() 16 { 17 int t; 18 cin>>t; 19 for(int i=0;i<t;i++) 20 { 21 cin>>n>>k; 22 cout<<dfs(n,k)<<endl; 23 } 24 return 0; 25 }
2019-03-28 19:19:17