洛谷P1358 扑克牌

题目描述

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

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

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

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

输入输出格式

输入格式:

第一行两个整数 为 n m

第二行 m个整数 ai

输出格式:

此数模10007后的结果

输入输出样例

输入样例#1: 
5 2
3 1
【样例输入2】
20 19
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
输出样例#1: 
【样例输出1】
20

【样例输出2】
8707

说明

【数据规模】对于50%的数据,M = 1。

数论题。。。
虽然被打上了 DP 的标签。。。
杨辉三角也算是背包。。。
附代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#define MAXN 110
#define MAXM 10010
#define MOD 10007
using namespace std;
int n,m,k,s=1,a[MAXN],f[MAXM][MAXN];
inline int read(){
	int date=0,w=1;char c=0;
	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
	return date*w;
}
void make(){
	for(int i=1;i<=MAXM;i++)f[i][1]=1;
	for(int i=2;i<=MAXM;i++)
	for(int j=2;j<=MAXN;j++)
	f[i][j]=(f[i-1][j-1]+f[i-1][j])%MOD;
}
int main(){
	m=read();n=read();
	k=m;
	make();
	for(int i=1;i<=n;i++){
		a[i]=read();
		s=(s*f[k+1][a[i]+1])%MOD;
		k-=a[i];
		if(k<0){
			printf("0\n");
			return 0;
		}
	}
	printf("%d\n",s);
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值