题意
题解
先考虑恰好吃个糖果的方案。由于有的限制,套路地想到容斥。枚举子集哪些不满足限制,然后把减去所有不满足的,剩下的就插板法就行了。假设枚举的集合中的,答案就是:
然后考虑到并不是恰好个,而是在的区间内,答案就是枚举,所有的情况加起来:
发现可以写成一个前缀和相减的形式,答案就是
所以只需要求
发现这个可以求:
所以就做完了…吗?
还有求组合数的问题。模数是合数,不能直接lucas。可以使用分解质因数再CRT合并,但比较麻烦。有一种方法就是这样:
- 因为有
- 所以有
这道题组合数只求,而范围是,所以在范围内,直接存下来模就行了。
具体见代码
CODE
#pragma GCC optimize ("O2")
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int mod = 2004;
const int MAXN = 2005;
LL facn = 1;
inline int C(int n, int m) {
LL re = 1;
for(int i = 1; i <= m; ++i)
re = re * (n-i+1) % (facn*mod);
return re / facn;
}
int n, m[15], sgn[(1<<10)+5];
inline int calc(int k) { return C(k+n, n); }
int main () {
int a, b, ans = 0;
scanf("%d%d%d", &n, &a, &b);
for(int i = 0; i < n; ++i) {
scanf("%d", &m[i]);
facn *= i+1;
}
sgn[0] = 1;
for(int s = 0; s < (1<<n); ++s) {
if(s&1) sgn[s] = -sgn[s>>1];
else sgn[s] = sgn[s>>1];
int t = 0;
for(int i = 0; i < n; ++i)
if(s&(1<<i)) t += m[i]+1;
int B = max(b-t, -1), A = max(a-t, 0);
if(A <= B) ans = (ans + 1ll * sgn[s] * (calc(B) - calc(A-1)) % mod) % mod;
}
printf("%d
", (ans + mod) % mod);
}