您的位置:首页 > 其它

[BZOJ3027][Ceoi2004]Sweet 容斥+组合数

2017-12-27 15:49 183 查看

3027: [Ceoi2004]Sweet

Time Limit: 1 Sec Memory Limit: 128 MB
Submit: 135 Solved: 66
[Submit][Status][Discuss]

Description

John得到了n罐糖果。不同的糖果罐,糖果的种类不同(即同一个糖果罐里的糖果种类是相同的,不同的糖果罐里的糖果的种类是不同的)。第i个糖果罐里有 mi个糖果。John决定吃掉一些糖果,他想吃掉至少a个糖果,但不超过b个。问题是John 无法确定吃多少个糖果和每种糖果各吃几个。有多少种方法可以做这件事呢?

Input

从标准输入读入每罐糖果的数量,整数a到b

John能够选择的吃掉糖果的方法数(满足以上条件)

Output

把结果输出到标准输出(把答案模 2004 输出)

1<=N<=10,0<=a<=b<=10^7,0<=Mi<=10^6

Sample Input

2 1 3

3

5

Sample Output

9

HINT

(1,0),(2,0),(3,0),(0,1),(0,2),(0,3),(1,1),(1,2),(2,1)

Source

对糖果是否装满容斥,通过插板法计算方案。

模数不为质数但n很小,可以将模数乘n!之后除n!。

1 #include<iostream>
2 #include<cstring>
3 #include<cstdio>
4 #include<cstdlib>
5 #include<cmath>
6 #include<algorithm>
7 #define LL long long
8 using namespace std;
9 LL n,a,b;
10 LL m[50];
11 LL mod=2004,mul=1;
12 LL c(LL x,LL y) {
13     if(x<y) return 0;
14     LL ans=1;
15     for(int i=x;i>=x-y+1;i--) ans=1LL*ans*i%mod;
16     return (ans/mul)%2004LL;
17 }
18 LL cnt(LL x) {
19     LL ans=0;
20     for(int i=0;i<(1<<n);i++) {
21         LL f=0,s=x;
22         for(int j=1;j<=n;j++) if((1<<(j-1))&i) f++,s-=m[j]+1;
23         if(s<0) continue;
24         if(f&1) ans-=c(s+n,n);
25         else ans+=c(s+n,n);
26         ans%=2004LL;
27     }
28     return ans;
29 }
30 int main() {
31     scanf("%lld%lld%lld",&n,&a,&b);
32     for(int i=1;i<=n;i++) scanf("%lld",&m[i]);
33     for(int i=1;i<=n;i++) mod*=i,mul*=i;
34     printf("%lld",((cnt(b)-cnt(a-1))%2004LL+2004LL)%2004LL);
35 }


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: