P8863 「KDOI-03」构造数组 题解
Thomas0702 · · 题解
模拟赛 T4。赛时认为这是不可做题,遂打爆搜拿 60pts 跑路。结果午睡之后再看很快就瞪出来做法了。所以是因为上午没有午睡导致脑子不清醒。
观察题目中的操作,每次选两个不同的下标进行
约定:
设
直接枚举转移即可。时间复杂度
#include<bits/stdc++.h>
#define ll long long
using namespace std;
void rd(){}
template<typename T,typename... U> void rd(T &x,U&... arg){
x=0;int f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') x=x*10+c-48,c=getchar();
x*=f;rd(arg...);
}
const int maxn=5005,maxv=30005,P=998244353;
int N,a[maxn],s[maxn];
ll f[2][maxv>>1],fac[maxv],inv[maxv];
inline ll C(int n,int m){
if(n<m||m<0) return 0;
return fac[n]*inv[m]%P*inv[n-m]%P;
}
int main(){
rd(N);
for(int i=1;i<=N;i++) rd(a[i]),s[i]=s[i-1]+a[i];
fac[0]=fac[1]=inv[0]=inv[1]=1;
for(int i=2;i<=s[N];i++)
fac[i]=fac[i-1]*i%P,
inv[i]=(P-P/i)*inv[P%i]%P;
for(int i=2;i<=s[N];i++) (inv[i]*=inv[i-1])%=P;
f[0][0]=1;
for(int i=1,t=1;i<=N;i++,t^=1){
memset(f[t],0,sizeof f[t]);
for(int j=0;j<=min(s[i-1],s[N]-s[i-1]);j++)
for(int k=0;k<=min(j,a[i]);k++){
if(j-k+a[i]-k>s[N]-s[i]) continue;
(f[t][j-k+a[i]-k]+=C(j,k)*
C(s[N]/2-(s[i-1]+j)/2,a[i]-k)%P*f[!t][j])%=P;
}
}
printf("%lld",f[N&1][0]);
return 0;
}