洛谷—— P1680 奇怪的分组

https://www.luogu.org/problemnew/show/1680

题目背景

终于解出了dm同学的难题,dm同学同意帮v神联络。可dm同学有个习惯,就是联络同学的时候喜欢分组联络,而且分组的方式也很特别,要求第i组的的人数必须大于他指定的个数ci。在dm同学联络的时候,v神在想,按照dm同学的规则一共可以有多少种方案呢?他想啊想,终于……没想出来。于是他又想到了聪明的你,你能帮v神算出按照dm同学的规则有多少种分组方案吗?

题目描述

v神的班级共有n个人,dm同学想把同学分成M组联络,要求第i组的人数必须大于给定的正整数Ci,求有多少不同的方案?(两个是相同的方案当且仅当对于任意的一队i,两个方案的第i组同学数量相等)由于结果很大,所以你只需要输出模1000000007的值。

输入输出格式

输入格式:

 

第一行两个整数N和M ,后面有M行,每行一个整数,表示Ci

 

输出格式:

 

仅有一行,一个整数,方案数模1000000007的值。

 

输入输出样例

输入样例#1: 复制
10 3
1
2
3
输出样例#1: 复制
3

说明

样例解释:

方案有三种,每组的个数分别是(3,3,4),(2,4,4),(2,3,5)。

数据范围约定:

对于30%的数据,N ,M<= 10

对于60%的数据,N ,M<=1000

对于100%的数据,N ,M<= 1000000 Ci<=1000

数据保证至少有一个方案

 

 

可以将题目看作,有 n- sigmaCi 个人,每个人去一个小组里,并要求每个小组至少有一人,

那么方案数即为 C(n-sigmaCi-1,m-1)

 1 #include <cstdio>
 2 
 3 #define LL long long
 4 
 5 inline void read(int &x)
 6 {
 7     x=0; register char ch=getchar();
 8     for(; ch>'9'||ch<'0'; ) ch=getchar();
 9     for(; ch>='0'&&ch<='9'; ch=getchar()) x=x*10+ch-'0';
10 }
11 
12 const int P(1000000007);
13 
14 LL fac[1000005];
15 
16 inline LL Pow(LL a,LL b)
17 {
18     LL ret=1;
19     for(; b; b>>=1,a*=a,a%=P)
20         if(b&1) ret=1ll*ret*a,ret%=P;
21     return ret;
22 }
23 
24 inline LL C(LL n,LL m)
25 {
26     fac[0]=1;
27     for(int i=1; i<=n; ++i)
28         fac[i]=1ll*fac[i-1]*i%P;
29     return 1ll*fac[n]*Pow(fac[m],P-2)%P*Pow(fac[n-m],P-2)%P;
30 }
31 
32 int Presist()
33 {
34     int n,m;
35     read(n),read(m);
36     for(int x,i=1; i<=m; ++i)
37         read(x), n-=x;
38     printf("%I64d\n",C(n-1,m-1));
39     return 0;
40 }
41 
42 int Aptal=Presist();
43 int main(int argc,char**argv){;}

 

posted @ 2017-11-27 20:15  Aptal丶  阅读(296)  评论(0编辑  收藏  举报