题意:
思路:
这个题显然可以容斥来写,刚学生成函数就来水一下。
对于每一堆
i
i
i我们写出其生成函数
F
i
(
x
)
=
∑
k
=
0
m
i
(
1
+
x
+
x
2
+
.
.
.
+
x
m
i
)
=
1
−
x
1
+
m
i
1
−
x
F_i(x)=\sum_{k=0}^{m_i}(1+x+x^2+...+x^{m_i})=\frac{1-x^{1+m_i}}{1-x}
Fi(x)=∑k=0mi(1+x+x2+...+xmi)=1−x1−x1+mi,那么将所有堆的生成函数乘起来即
G
(
x
)
=
∏
i
=
1
n
F
i
(
x
)
=
∏
i
=
1
n
1
−
x
1
+
m
i
1
−
x
=
(
1
−
x
)
−
n
∗
∏
i
=
1
n
(
1
−
x
1
+
m
i
)
G(x)=\prod_{i=1}^nF_i(x)=\prod_{i=1}^n \frac{1-x^{1+m_i}}{1-x}=(1-x)^{-n}*\prod_{i=1}^n(1-x^{1+m_i})
G(x)=∏i=1nFi(x)=∏i=1n1−x1−x1+mi=(1−x)−n∗∏i=1n(1−x1+mi),对于后面的这项,由于
n
n
n很小,所以展开最多只有
2
n
2^n
2n项,直接暴力展开即可。
对于前面的,我们用牛顿二项式定理展开
(
1
−
x
)
−
n
=
∑
i
≥
0
(
n
+
i
−
1
i
)
x
i
(1-x)^{-n}=\sum_{i\ge0}\binom{n+i-1}{i}x^i
(1−x)−n=∑i≥0(in+i−1)xi,可以得到对应的
x
x
x项的系数,所以我们直接枚举
∏
i
=
1
n
(
1
−
x
1
+
m
i
)
\prod_{i=1}^n(1-x^{1+m_i})
∏i=1n(1−x1+mi)展开之后的指数为
k
k
k的系数
t
k
t_k
tk,让后计算前面的项对答案的贡献,即
t
k
∗
∑
i
=
a
−
k
b
−
k
(
n
−
1
−
i
i
)
t_k*\sum_{i=a-k}^{b-k}\binom{n-1-i}{i}
tk∗∑i=a−kb−k(in−1−i),考虑将其转换成一个前缀和的形式,考虑到有
∑
i
=
0
k
(
n
−
1
+
i
i
)
=
(
n
+
k
n
)
\sum_{i=0}^k\binom{n-1+i}{i}=\binom{n+k}{n}
∑i=0k(in−1+i)=(nn+k),所以对上面式子进行化简
c
k
∗
(
(
n
+
b
−
k
b
−
k
)
−
(
n
+
a
−
k
−
1
a
−
k
−
1
)
)
c_k*(\binom{n+b-k}{b-k}-\binom{n+a-k-1}{a-k-1})
ck∗((b−kn+b−k)−(a−k−1n+a−k−1)),其实到这里应该就已经结束了,直接枚举
2
k
2^k
2k个
c
k
c_k
ck让后直接得到答案即可。但是这个题模数不是个质数,而且组合数很大,所以考虑将其转换为
c
k
∗
(
(
n
+
b
−
k
n
)
−
(
n
+
a
−
k
−
1
n
)
)
c_k*(\binom{n+b-k}{n}-\binom{n+a-k-1}{n})
ck∗((nn+b−k)−(nn+a−k−1)),这样最多只有
n
n
n项,且分母是
n
!
n!
n!,我们将模数乘上
n
!
n!
n!,在计算组合数的时候将其模上即可,这样就可避免组合数过大。
调了半天,代码很丑。。
//#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native")
//#pragma GCC optimize(2)
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#include<cassert>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid ((tr[u].l+tr[u].r)>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std;
//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); }
//void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); }
//void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;
const int N=20000010,INF=0x3f3f3f3f;
const double eps=1e-6;
int n,a,b;
LL mod=2004;
int p[20];
LL inv[N],fun[N],now;
LL C(int a,int b)
{
if(a<0||b<0||a<b) return 0;
LL noww=1;
for(int i=a,j=b;j;i--,j--) (noww*=1ll*i%mod)%=mod;
return (noww/now)%2004;
}
int main()
{
// ios::sync_with_stdio(false);
// cin.tie(0);
cin>>n>>a>>b;
now=1;
for(int i=2;i<=n;i++) now*=i; mod*=now;
for(int i=1;i<=n;i++) scanf("%d",&p[i]),p[i]++;
map<int,int>mp;
mp[0]=1;
for(int i=1;i<=n;i++) {
map<int,int>now=mp;
for(auto x:mp) {
now[x.X+p[i]]+=x.Y*(-1);
}
mp=now;
}
LL ans=0;
for(auto x:mp) {
int c=x.Y,k=x.X;
LL now=(C(n+b-k,n)-C(n+a-k-1,n))%2004;
ans+=c*now%2004; ans%=2004;
ans+=2004; ans%=2004;
}
printf("%lld\n",ans);
return 0;
}
/*
*/