# 【洛谷5339】[TJOI2019] 唱、跳、rap和篮球（容斥+NTT）

### 容斥

$\sum_{k=0}^{min(\lfloor\frac n4\rfloor,a,b,c,d)}(-1)^kS(k)$

$S(k)=C_{n-3k}^k\sum_{i=0}^{a-k}\sum_{j=0}^{b-k}\sum_{p=0}^{c-k}\sum_{q=0}^{d-k}[i+j+p+q=n-4k]\frac{(n-4k)!}{i!j!p!q!}$

$S(k)=C_{n-3k}^k\cdot(n-4k)!\cdot\sum_{i=0}^{a-k}\sum_{j=0}^{b-k}\sum_{p=0}^{c-k}\sum_{q=0}^{d-k}[i+j+p+q=n-4k](\frac1i\cdot\frac1j\cdot\frac1p\cdot\frac1q)$

### 代码

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 1000
#define X 998244353
#define C(x,y) (1LL*Fac[x]*IFac[y]%X*IFac[(x)-(y)]%X)
using namespace std;
int n,a,b,c,d,s[N+5],Fac[N+5],IFac[N+5];
I int Qpow(RI x,RI y) {RI t=1;W(y) y&1&&(t=1LL*t*x%X),x=1LL*x*x%X,y>>=1;return t;}//快速幂
template<int SZ,int PR> class Poly//多项式算法
{
private:
int IPR,P,L,R[4*N+5],A[4*N+5],B[4*N+5],C[4*N+5],D[4*N+5];
I void T(int *s,CI op)
{
RI i,j,k,U,S,x,y;for(i=0;i^P;++i) i<R[i]&&(x=s[i],s[i]=s[R[i]],s[R[i]]=x);
for(i=1;i^P;i<<=1) for(U=Qpow(~op?PR:IPR,(X-1)/(i<<1)),j=0;j^P;j+=i<<1)
for(S=1,k=0;k^i;++k,S=1LL*S*U%X) s[j+k]=((x=s[j+k])+(y=1LL*S*s[i+j+k]%X))%X,s[i+j+k]=(x-y+X)%X;
}
public:
I Poly() {IPR=Qpow(PR,X-2);}
I int NTT(CI n,CI a,CI b,CI c,CI d)//求出长度为a,b,c,d的四个多项式卷积的n次项的系数
{
RI i;P=1,L=0;W(P<=a+b+c+d) P<<=1,++L;for(i=0;i^P;++i) R[i]=(R[i>>1]>>1)|((i&1)<<L-1);
for(i=0;i<=a;++i) A[i]=IFac[i];for(;i<P;++i) A[i]=0;
for(i=0;i<=b;++i) B[i]=IFac[i];for(;i<P;++i) B[i]=0;
for(i=0;i<=c;++i) C[i]=IFac[i];for(;i<P;++i) C[i]=0;
for(i=0;i<=d;++i) D[i]=IFac[i];for(;i<P;++i) D[i]=0;
for(T(A,1),T(B,1),T(C,1),T(D,1),i=0;i^P;++i) A[i]=1LL*A[i]*B[i]%X*C[i]%X*D[i]%X;//NTT
return T(A,-1),1LL*A[n]*Qpow(P,X-2)%X;//返回答案
}
};Poly<N,3> P;
int main()
{
RI i;for(scanf("%d%d%d%d%d",&n,&a,&b,&c,&d),Fac[0]=i=1;i<=n;++i) Fac[i]=1LL*Fac[i-1]*i%X;//预处理阶乘
for(IFac[n]=Qpow(Fac[n],X-2),i=n-1;~i;--i) IFac[i]=1LL*IFac[i+1]*(i+1)%X;//预处理阶乘逆元
RI j,ans=0,lim=min(n/4,min(min(a,b),min(c,d)));for(i=0;i<=lim;++i)//容斥
ans=(1LL*(i&1?X-1:1)*C(n-3*i,i)%X*Fac[n-4*i]%X*P.NTT(n-4*i,a-i,b-i,c-i,d-i)+ans)%X;//计算答案
return printf("%d",ans),0;
}

posted @ 2019-12-23 20:24  TheLostWeak  阅读(...)  评论(...编辑  收藏