传送门
文章目录
- 题意:
- 思路:
题意:
思路:
这个题显然可以容斥来写,刚学生成函数就来水一下。
对于每一堆iii我们写出其生成函数Fi(x)=∑k=0mi(1+x+x2+...+xmi)=1−x1+mi1−xF_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=1nFi(x)=∏i=1n1−x1+mi1−x=(1−x)−n∗∏i=1n(1−x1+mi)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),对于后面的这项,由于nnn很小,所以展开最多只有2n2^n2n项,直接暴力展开即可。
对于前面的,我们用牛顿二项式定理展开(1−x)−n=∑i≥0(n+i−1i)xi(1-x)^{-n}=\sum_{i\ge0}\binom{n+i-1}{i}x^i(1−x)−n=∑i≥0(in+i−1)xi,可以得到对应的xxx项的系数,所以我们直接枚举∏i=1n(1−x1+mi)\prod_{i=1}^n(1-x^{1+m_i})∏i=1n(1−x1+mi)展开之后的指数为kkk的系数tkt_ktk,让后计算前面的项对答案的贡献,即tk∗∑i=a−kb−k(n−1−ii)t_k*\sum_{i=a-k}^{b-k}\binom{n-1-i}{i}tk∗∑i=a−kb−k(in−1−i),考虑将其转换成一个前缀和的形式,考虑到有∑i=0k(n−1+ii)=(n+kn)\sum_{i=0}^k\binom{n-1+i}{i}=\binom{n+k}{n}∑i=0k(in−1+i)=(nn+k),所以对上面式子进行化简ck∗((n+b−kb−k)−(n+a−k−1a−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)),其实到这里应该就已经结束了,直接枚举2k2^k2k个ckc_kck让后直接得到答案即可。但是这个题模数不是个质数,而且组合数很大,所以考虑将其转换为ck∗((n+b−kn)−(n+a−k−1n))c_k*(\binom{n+b-k}{n}-\binom{n+a-k-1}{n})ck∗((nn+b−k)−(nn+a−k−1)),这样最多只有nnn项,且分母是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;
}
/**/