zoukankan      html  css  js  c++  java
  • P1358 扑克牌

    题目描述

    组合数学是数学的重要组成部分,是一门研究离散对象的科学,它主要研究满足一定条件的组态(也称组合模型)的存在、计数以及构造等方面的问题。组合数学的主要内容有组合计数、组合设计、组合矩阵、组合优化等。

    随着计算机科学的日益发展,组合数学的重要性也日渐凸显,因为计算机科学的核心内容是使用算法处理离散数据。

    今天我们来研究组合数学中的一个有趣的问题,也是一个简单的计数问题:

    从一副含有 nn 张的扑克牌(每张扑克牌都不相同)中,分给 mm 个人,第 ii 个人得到 a_iai 张牌,求一共有几种分法,这个数可能非常大,请输出此数模 1000710007 后的结果。

    输入格式

    第一行两个整数为 n,mn,m。

    第二行 mm 个整数 a_iai

    输出格式

    此数模 1000710007 后的结果。

    输入输出样例

    输入 #1
    5 2
    3 1
    
    输出 #1
    20
    
    输入 #2
    20 19
    1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
    
    输出 #2
    8707
    

    说明/提示

    对于 50\%50% 的数据:M=1M=1。

    对于 100\%100% 的数据:1 leq n leq 10^41n104,1 leq m leq 1001m100,0 leq a_i leq 1000ai100。

    解析:题目很容易发现用到是组合数和乘法原理。

    给第1个人分配的方法数为:c(n,a[1]);

    给第2个人分配的方法数为:c(n-a[1],a[2]);

    ...

    给第n个人分配的方法数为:c(n-a[1]-a[2]-...a[n-1],a[n]);

    利用乘法原理,总的方法数为:c(n,a[1])*c(n-a[1],a[2])*...*c(n-a[1]-a[2]-...a[n-1],a[n])

    利用杨辉三角,提前算出所有的组合数。注意m<=100,也就是最多用到杨辉三角第100列的数。

     代码如下:

    #include<iostream>
    #include<cstdio>
    using namespace std;
    const int maxm=110;
    int n,m,sum=1;
    int a[maxm],f[10010][maxm];
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=m;i++) scanf("%d",&a[i]);
    	f[0][0]=1;
    	f[1][0]=1;f[1][1]=1;
    	for(int i=2;i<=n;i++){
    		f[i][0]=1;
    		for(int j=1;j<=min(i,100);j++){//m最大为100,也就是最多用到第100列的值 
    			f[i][j]=(f[i-1][j-1]+f[i-1][j])%10007;
    		//	cout<<f[i][j]<<" ";
    		}
    	//	cout<<endl;
    			
    	}	
    	for(int i=1;i<=m;i++){
    	//	cout<<sum<<" ";
    		sum=(sum*f[n][a[i]])%10007;
    	//	cout<<f[n][a[i]]<<endl;
    		n-=a[i];
    	}
    	printf("%d
    ",sum);				
    	return 0;
    }
    

      

  • 相关阅读:
    十二、 Spring Boot 静态资源处理
    九、 Spring Boot 拦截器
    docker之搭建私有仓库
    docker之Dokcerfile 常用指令
    docker之网络管理
    docker之故障问题解决方案
    docker之搭建LNMP
    docker之容器数据持久化
    都说岁月不饶人,我们又何曾饶过岁月
    docker之容器管理
  • 原文地址:https://www.cnblogs.com/ssfzmfy/p/12835371.html
Copyright © 2011-2022 走看看