zoukankan      html  css  js  c++  java
  • 盒子放球

    盒子放球问题

    第一类:

    将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;
    }

     

  • 相关阅读:
    信息安全基本概念
    GmSSL开发环境搭建及双证书生成
    Git使用教程
    linux软件管理
    在Windows中查看文件的MD5值
    odoo显示页面格式化日期的一个方法
    Ubuntu 查看文件夹大小
    docker容器中启动postgresql 9.5失败:could not locate a valid checkpoint record
    如何让postgresql日志记录所有的执行语句
    vim快捷键
  • 原文地址:https://www.cnblogs.com/LinKArftc/p/4902594.html
Copyright © 2011-2022 走看看