3027: [Ceoi2004]Sweet
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 65 Solved: 31
[ 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
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
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<bitset>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;
const int mo = 2004;
const int N = (1 << 13);
typedef long long LL;
inline int Mul(const int &x,const int &y) {return x * y % mo;}
inline int Add(const int &x,const int &y) {return x + y < mo ? x + y : x + y - mo;}
inline int Dec(const int &x,const int &y) {return x - y >= 0 ? x - y : x - y + mo;}
inline int gcd(int x,int y) {return !y ? x : gcd(y,x % y);}
struct data{
int d,k; data(){}
data(int d,int k): d(d),k(k){}
data operator * (const data &b)
{
data ret; ret.d = Mul(d,b.d);
ret.k = k + b.k; return ret;
}
}D[N];
int n,tot,a,b,fac = 1;
inline int C(int N)
{
int tmp = fac,ret = 1;
for (int i = 0; i < n; i++)
{
int now = N - i,G = gcd(now,tmp);
now /= G; tmp /= G;
ret = Mul(ret,now % mo);
}
return ret;
}
int Calc(int now)
{
int ret = 0;
for (int i = 1; i <= tot; i++)
{
if (D[i].k > now) continue;
ret = Add(ret,Mul(D[i].d,C(now - D[i].k + n)));
}
return ret;
}
int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif
cin >> n >> a >> b; D[tot = 1] = data(1,0);
for (int i = 1; i <= n; i++) fac *= i;
for (int i = 1; i <= n; i++)
{
int x,cur = tot; scanf("%d",&x);
data now = data(2003,x + 1);
for (int j = 1; j <= cur; j++)
{
data Nex = D[j] * now;
if (Nex.k > b) continue;
D[++tot] = Nex;
}
}
cout << Dec(Calc(b),Calc(a - 1)) << endl;
return 0;
}