P1358 撲克牌

題目描述

組合數學是數學的重要組成部分,是一門研究離散對象的科學,它主要研究知足必定條件的組態(也稱組合模型)的存在、計數以及構造等方面的問題。組合數學的主要內容有組合計數、組合設計、組合矩陣、組合優化等。html

隨着計算機科學的日益發展,組合數學的重要性也日漸凸顯,由於計算機科學的核心內容是使用算法處理離散數據。ios

今天咱們來研究組合數學中的一個有趣的問題,也是一個簡單的計數問題:算法

從一副含有 nn 張的撲克牌(每張撲克牌都不相同)中,分給 mm 我的,第 ii 我的獲得 a_iai 張牌,求一共有幾種分法,這個數可能很是大,請輸出此數模 1000710007 後的結果。優化

輸入格式

第一行兩個整數爲 n,mn,m。spa

第二行 mm 個整數 a_iai設計

輸出格式

此數模 1000710007 後的結果。3d

輸入輸出樣例

輸入 #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。orm

對於 100\%100% 的數據:1 \leq n \leq 10^41n104,1 \leq m \leq 1001m100,0 \leq a_i \leq 1000ai100。htm

解析:題目很容易發現用到是組合數和乘法原理。對象

給第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\n",sum);				
	return 0;
}
相關文章
相關標籤/搜索