3027: [Ceoi2004]Sweet

3027: [Ceoi2004]Sweet

Time Limit: 1 Sec   Memory Limit: 128 MB
Submit: 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

Sample Output

9

HINT

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

Source

[ Submit][ Status][ Discuss]

#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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值