CEOI 2004 sweets 容斥原理

题意:有n种糖果,第i种糖果有mi个,求吃掉至少a个,不超过b个糖果的方案数模2004。

数据规模:

n ≤ 10; mi ≤ 10^6;  ab ≤ 10^7
 
思路:原题可转化为不等式 xi≤mi a ≤Σxi≤b 的解的个数
可新建一个变量 xn≤b-a
则可变为  xi≤mi Σxi=b
因为n非常小 容斥原理求解
 
 
 1 #include<iostream>
2 #include<cstdio>
3 #include<cmath>
4 #include<cstring>
5 using namespace std;
6 #define mod 2004
7 int n,a,b;
8 int p[20],num[20];
9 int factor[10];
10 void divide(int n)
11 {
12 memset(factor,0,sizeof(factor));
13 int i,j,x=1;
14 for(i=1;i<=n;i++) x=x*i;
15 for(i=2;i<=10;i++)
16 {
17 while(x%i==0)
18 {
19 factor[i]++; x/=i;
20 }
21 }
22 }
23 void update(int x)
24 {
25 int j=factor[x];
26 for(int i=1;i<=n-1;i++)
27 {
28 while(num[i]%x==0&&j>0)
29 {
30 num[i]/=x; j--;
31 }
32 }
33 }
34 int combination(int x,int y)
35 {
36 if(x<y) return 0;
37 int i,j;
38 long long ans=1;
39 for(i=1;i<=y;i++)
40 num[i]=x-y+i;
41 update(2); update(3); update(5); update(7);
42 for(i=1;i<=y;i++) ans=ans*num[i]%mod;
43 return ans;
44 }
45 int calc(int x,int b)
46 {
47 int i;
48 for(i=0;i<n;i++)
49 if(x&(1<<i)) b-=p[i];
50 return combination(b-1,n-1);
51 }
52 int solve()
53 {
54
55 int ans=0;
56 int tot=(1<<n);
57 int i,j,cc;
58 for(i=0;i<tot;i++)
59 {
60 cc=0;
61 for(j=0;j<n;j++)
62 if(i&(1<<j)) cc++;
63 if(cc%2==0) ans+=calc(i,b);
64 else ans-=calc(i,b);
65 }
66 return (ans%mod+mod)%mod;
67 }
68 int main()
69 {
70 cin>>n>>a>>b;
71 int i;
72 for(i=0;i<n;i++)
73 {
74 cin>>p[i]; p[i]++;
75 }
76 p[n++]=b-a+1;
77 divide(n-1);
78 b=b+n;
79 printf("%d\n",solve());
80 return 0;
81 }

posted on 2012-03-11 08:31  myoi  阅读(550)  评论(0编辑  收藏  举报

导航