[ACM] POJ 1664 放苹果(n个相同小球放入m个相同盒子)

来源:互联网 发布:理光软件研究所待遇 编辑:程序博客网 时间:2024/05/22 16:39

放苹果
Time Limit: 1000MS Memory Limit: 10000KTotal Submissions: 25952 Accepted: 16509

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

17 3

Sample Output

8

Source

lwx@POJ


将n个相同的小球放入m个相同的盒子,问有多少种方法。

 解析:有些题目可以转化为这样的题目,比如有n个相同的小球,m个相同的盒子,要求每个盒子里面至少有k个小球,问一共有多少种方法:http://blog.csdn.net/duanxian0621/article/details/7864791  方法为:预先在每个盒子里面已经放好k个小球,那么还剩下n-k*m 个小球,然后就转化为了,把n-k*m个相同的小球放入m个相同的盒子里面,有多少种方法。

 

分情况讨论:a[i][j]表示i个小球放入j个盒子的方法数

①    当放入小球后,球数最少的盒子为空,那么就相当于,把i个小球放入j-1个盒子里面,即a[i][j-1]。

②    当放入小球后,球数最少的盒子不为空,那么说明每个盒子里面都至少有一个小球,那么就预先把每个盒子里面放入一个小球好了,有 a[i-j] [j]。

所以 ,递推公式为 a[i][j]= a[i][j-1]+a[i-j][j],这里是i>=j的。

当i<j的时候,无论怎么放,肯定会存在空盒,不妨先拿走一个空盒(保证有空盒),然后把i个相同的小球放入剩余的j-1个相同的盒子中,有a[i][j-1]种方法,所以a[i][j]=a[i][j-1].

 

综上:将n个相同的小球放入m个相同的盒子有

当i>=j时,a[i][j]=a[i][j-1]+a[i-j][j];

当i<时,a[i][j]=a[i][j-1],(仔细想想,这里也可以写成a[i][j]=a[i][i],因为a[i][i]=a[i][i+1]=a[i][i+2]=a[i][i+3]……..

初始化a数组代码为:

int a[maxn][maxn];

void prepare()

{

   for (int i=0;i<m;i++)

   a[i][1]=a[0][i]=1;

   for (int i=1;i<maxn;i++)

       for (int j=2;j<maxn;j++)

           if (j<=i)

               a[i][j]=(a[i-j][j]+a[i][j-1])%MOD;

           else

               a[i][j]=a[i][i]; //其实是a[i][j-1],不过和a[i][i]是一样的。

}

代码:

#include <iostream>using namespace std;const int maxn=11;int a[maxn][maxn];void init(){    for(int i=1;i<=10;i++)        a[0][i]=1,a[i][1]=1;    for(int i=1;i<maxn;i++)        for(int j=2;j<=maxn;j++)            if(j<=i)                a[i][j]=a[i][j-1]+a[i-j][j];            else                a[i][j]=a[i][i];}int main(){    init();    int t,n,m;    cin>>t;    while(t--)    {        cin>>n>>m;        cout<<a[n][m]<<endl;    }    return 0;}


1 0
原创粉丝点击