描述
把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?
(注意:假如有3个盘子7个苹果,5,1,1和1,5,1 是同一种分法。)
输入
t,表示测试组数(t<=10) 然后t行,每行包含两个数M,N.(1<=M,N<=10)
输出
输出不同的分法
样例输入
1
7 3
样例输出
8
分析转自:http://uzone.univs.cn/blog_2984978_mgf8x9eow0qnb2wreow1.html
分析:放法要分盘子全放满了和没放满的情况。
由于当(1):苹果数少于盘子数时,此时把盘子减少一个,对结果没影响。(为什
么?试想如果10个苹果放1000个盘子,是不是很多盘子没用呢?嘿嘿)这样此时 fun(m,n)=fun(m,n-1);
(2):苹果数少于盘子数,此时仍可以分成两种情况:放满和没有放满。
没放满:fun(m,n)转化成fun(m,n-1)(因为你有盘子没用)
放满 :放满即为每个盘子都有苹果,那么我把每个盘子的苹果拿一个出来结果仍然会是一样。此时的fun(m,n)转化成fun(m-n,m);(既然每个盘子必须有个苹果,那么这些苹果的存在与否可以当作不影响结果,比如拿5个苹果放2个盘子,又要满足每个盘子必须有个苹果的话那肯定有两个苹果不能动,必须放在盘子下,然后他们就与盘子融为一体,我们就当作看不见他们了。。。。。嘿嘿);
好了,函数进来盘子与苹果的数量关系每次都满足上面的两种情况,每次又归化成更简单的继续下去,那么很显然就想到了递归。
代码如下:
#include<stdio.h>
int fun(int m,int n)
{
if(m<=1||n==1)
return 1;//为m可能为和n相等,此时如果要满足每个盘子都有的话只有一种放法。只有一个盘子也只有一种
if(n==0)
return 0;
if(n>m)//至少有一个盘子为空
return fun(m,n-1);
else//至少一个盘子为空 + 所有盘子都不为空
return fun(m,n-1)+fun(m-n,n);
}
int main()
{
printf("%d\n",fun(7,3));
}
public static void main(String args[]){ int a,m,n; Scanner sc=new Scanner(System.in); a=sc.nextInt(); while(a>0){ m=sc.nextInt(); n=sc.nextInt(); System.out.println(num(m,n)); a--; } } public static int num(int m,int n){ if(m==0||n==1){ return 1; } if(n>m){ return num(m,m); } else{ return num(m,n-1)+num(m-n,n); } }
