zoukankan      html  css  js  c++  java
  • luogu P1358 扑克牌 |数学

    题目描述

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

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

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

    从一副含有n(n≤10000)张的扑克牌[显然每张扑克牌都不相同]中,分给m(m≤100)个人,第i个人得到ai (0≤ai≤100)张牌,求一共有几种分法,这个数可能非常大,请输出此数模10007后的结果。

    输入格式

    第一行两个整数 为 n m

    第二行 m个整数 ai

    输出格式

    此数模10007后的结果


    n个不同物品,m个组,每个组有容量,求物品放置方案数

    ans=C(a[1],n)C(a[2],n-a[1])C(a[3],n-a[1]-a[2])...

    简化一下

    (ans=prod_{i=1}^m) (C(a[i],n-sum[i-1]))

    预处理C数组,然后按照公式算就可以了

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int mod=10007,N=1e4+5;
    #define int long long
    int n,m,a[N],sum[N];
    int jc[N],inv[N];
    inline int ksm(int x,int y){int ans=1;while(y){if(y&1)ans=ans*x%mod;x=x*x%mod;y>>=1;}return ans;}
    int C(int x,int y){if(x>y)return 0;return jc[y]*inv[x]%mod*inv[y-x]%mod;}
    inline void pre(){
    	jc[0]=1;for(int i=1;i<=n;i++)jc[i]=jc[i-1]*i%mod;
    	inv[n]=ksm(jc[n],mod-2);
    	for(int i=n-1;i>=0;i--)inv[i]=inv[i+1]*(i+1)%mod;
    }
    signed main(){
    	cin>>n>>m;pre();
    	for(int i=1;i<=m;i++)scanf("%lld",&a[i]),sum[i]=sum[i-1]+a[i];
    	int ans=1;
    	for(int i=1;i<=m;i++)
    	ans=(ans*C(a[i],n-sum[i-1]))%mod;
    	cout<<ans<<endl;
    }
    
  • 相关阅读:
    图片放大功能
    谈论算法
    socket基础
    js实现快速排序
    mysql死锁问题分析(转)
    MVCC 专题
    ActiveMQ持久化方式(转)
    消息队列中点对点与发布订阅区别(good)
    tomcat下部署activemq(转)
    Android文件下载(实现断点续传)
  • 原文地址:https://www.cnblogs.com/naruto-mzx/p/11768441.html
Copyright © 2011-2022 走看看