• Luogu 题解 P2638 【安全系统】


    组合数学


    题目

    题意:有两种不同的球,放入n个箱子中,箱子可以放,也可以不放
    分析:这是一种经典组合题,即往盒子中装球,我们由小学奥数可以得出结论:
    ( ext{ans = }sum^{a}_{i = 0} sum^{b}_{j = 0} ext{C[i + n - 1][n - 1] C[j + n - 1][n - 1]})

    我们得到公式后,还需要一个高效计算组合数的算法,这是我们便想到了杨氏三角:
    众所周知

            1
           1 1
          1 2 1
         1 3 3 1
        1 4 6 4 1
        .........
    

    于是我们得到了一个公式:
    C[i][j] = C[i - 1][j - 1] + C[i - 1][j]
    其中当j == 0 || j == i时,C[i][j] = 1

    得到了一段预处理组合数的代码:

    void Pre_Work() {
    	for(int i = 0; i <= 50; i ++) con[i][0] = con[i][i] = 1;
    	for(int i = 2; i <= 50; i ++)
    		for(int j = 1; j <= i; j ++)
    			con[i][j] = con[i - 1][j] + con[i - 1][j - 1];
    }
    
    #include <cstdio>
    #include <iostream>
    #define int unsigned long long
    //注意要用ull
    using namespace std;
    int read() {
    	int w = 1,res = 0;
    	char ch = getchar();
    	while(ch < '0' || ch > '9') {
    		if(ch == '-') w = -1;
    		ch = getchar();
    	}
    	while(ch >= '0' && ch <= '9') res = res * 10 + ch - '0', ch = getchar();
    	return w * res;
    }
    int con[100][100], ans;
    void Pre_Work() {
    	for(int i = 0; i <= 50; i ++) con[i][0] = con[i][i] = 1;
    	for(int i = 2; i <= 50; i ++)
    		for(int j = 1; j <= i; j ++)
    			con[i][j] = con[i - 1][j] + con[i - 1][j - 1];
    }
    signed main() {
    	int n = read(), a = read(), b = read();
    	Pre_Work();
    	for(int i = 0; i <= a; i ++)
    		for(int j = 0; j <= b; j ++)
    			ans += con[i + n - 1][n - 1] * con[j + n - 1][n - 1];
    	cout << ans;
    	return 0;
    }
    
  • 相关阅读:
    ActiveX控件开发 C#
    sql server中新增一条数据后返回该数据的ID
    数据库设计之用户-角色-权限分配
    C#面向对象基础
    单片机通讯协议
    MSDN上的异步socket 服务端例子
    文件操作
    socket+select模型
    HSV颜色模型
    视觉软件需要考虑的10个方面
  • 原文地址:https://www.cnblogs.com/Wuzhuoming-sirenboke/p/14064372.html
Copyright © 2020-2023  润新知