POJ-1664
放苹果
Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 30213 Accepted: 19053 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 3Sample Output
8
本题可以看成典型的整数分解问题。将m个苹果放到n个盘子里时可以分为两种情况,我们设a(m,n)表示结果总数,当全部n个盘子都不为0时,即每个盘子至少有一个苹果,这时我们可以将总数看为a(m-n,n);当有一个空盘时,可以看做m个苹果放入n-1个盘子中,即a(m,n-1)(无需考虑多个空盘的情况,递归时自然会出现)。这时我们可得方程a(m,n)=a(m,n-1)+a(m-n,n)。下面我们来讨论几种特殊情况,首先就是m为1/0和n为1/0的情况,显而易见,a(m,1)、a(m,0)、a(1,n)、a(0,n)的结果皆为1。其次就是m<n时,a(m,n)的结果与a(m,m)的结果相同,故当m<n时,a(m,n)=a(m,m)。
我们也可以这样理解a(m,n-1)加一个空盘0即为a(m,n)含0的情况,a(m-n,n)在每一个盘子里加1个苹果即为a(m,n)且不会影响结果,这就是不含0的情况。所以a(m,n-1)和a(m-n,n)组成了a(m,n)即a(m,n)=a(m,n-1)+a(m-n,n)。
附AC代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 7 const int MAX=12; 8 9 int a[MAX][MAX]; 10 11 int main(){ 12 int i,j,t,m,n; 13 for(i=0;i<MAX;i++){ 14 a[0][i]=1; 15 a[1][i]=1; 16 a[i][0]=1; 17 a[i][1]=1; 18 } 19 for(i=2;i<MAX;i++){ 20 for(j=2;j<MAX;j++){ 21 if(i>=j) 22 a[i][j]=a[i][j-1]+a[i-j][j]; 23 else 24 a[i][j]=a[i][i]; 25 } 26 } 27 while(~scanf("%d",&t)){ 28 while(t--){ 29 scanf("%d %d",&m,&n); 30 if(m>=n) 31 printf("%d\n",a[m][n]); 32 else 33 printf("%d\n",a[m][m]); 34 } 35 } return 0; 36 }