• 盒子放球


    盒子放球问题

    第一类:

    将k个球放入n个不同的盒子中,每个盒子放球数>=0,求方法数

    假设n个盒子分别放x1,x2,x3...xn,则x1+x2+x3+...+xn=k,令yi=xi+1(1<=i<=n),则yi>=1y1+y2+...+yn=n+k,相当于求yi这个方程的解组数,可以看成插板问题,往n+k个物品中插入n-1个板,所以答案是C(n+k-1,n-1)=C(n+k-1,k)

    /*
     *输入说明:k个相同的球放入n个不同的盒子
     *输入每行有两个正整数n和k
     */
    int com(int n, int m) {
        m = min(m, n - m);
        int res = 1;
        for (int i = 0, j = 1; i < m; i ++) {
            res *= n - i;
            while (j <= m && res % j == 0) {
                res /= j;
                j ++;
            }
        }
        return res;
    }
    
    int main() {
    
        int n, k;
        while (~scanf("%d %d", &n, &k)) {
            printf("%d
    ", com(n+k-1, k));
        }
    
        return 0;
    }

    第二类:

    m个相同的球放入n个相同的盒子,每个盒子放球数>=0,求方法数

    令dp[i][j]表示i个球放入j个盒子的方法数。

    当i>j时,分两种情况:

    1、每个盒子至少放一个,为dp[i-j][j]

    2、存在某个盒子不放,为dp[i][j-1]

    所以dp[i][j] = dp[i-j][j] + dp[i][j-1];

    当i<=j时,等价于i个球放入i个盒子

    const int maxn = 20;
    
    int dp[maxn][maxn];//i个球放入j个盒子方法数
    
    void init() {
        for (int j = 1; j <= 10; j ++) dp[0][j] = dp[1][j] = dp[j][1] = dp[j][0] = 1;
        for (int i = 2; i <= 10; i ++) {
            for (int j = 2; j <= 10; j ++) {
                if (i >= j) dp[i][j] = dp[i-j][j] + dp[i][j-1];
                else dp[i][j] = dp[i][i];
            }
        }
    }
    
    int main() {
    
        init();
        int T, m, n;
        scanf("%d", &T);
        while (T --) {
            scanf("%d %d", &m, &n);
            printf("%d
    ", dp[m][n]);
        }
        return 0;
    }

     

  • 相关阅读:
    定时器与休眠
    进程的创建
    详述进程创建和程序执行
    线程
    会话,进程组,作业控制
    进程优先级和调度
    进程资源
    日志信息log
    能力
    浅谈产品模型(Profile)在程序设计中的作用
  • 原文地址:https://www.cnblogs.com/LinKArftc/p/4902594.html
Copyright © 2020-2023  润新知