题解 P7501
思路
下文记
-
\text{type}=0
显然如果答案存在,我们放完所有兵营后必定还剩下
因此,我们只需要在
-
\text{type}=1
考虑钦定两侧兵营的
若最左侧为第
因此,我们可以做到
注意到
代码
//愿神 zhoukangyang 指引我。
#include<bits/stdc++.h>
#define int long long
using namespace std;
inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
int a[1000003],b[1000003];
const int p=998244353;
int n=read(),m=read(),op=read();
int qp(int x,int y)
{
int res=1;
for(int t=x; y; y>>=1,t=t*t%p) if(y&1) res=res*t%p;
return res;
}
int fac[1000003],ifac[1000003];
int A(int n,int m)
{
if(n<m) return 0;
return fac[n]*ifac[n-m]%p;
}
int C(int n,int m)
{
if(n<m) return 0;
return fac[n]*ifac[n-m]%p*ifac[m]%p;
}
void solve0()
{
int s=0;
for(int i=1; i<=n; ++i) s+=a[i];
if(s>m)
{
puts("0");
return ;
}
int A=(m-s)+n,ans=1;
for(int i=A; i>A-n; --i) ans=ans*i%p;
printf("%lld\n",ans);
return ;
}
int G[2003],S[1003];
void solve1()
{
if(n==1)
{
printf("%lld\n",m);
return ;
}
int s=0;
fac[0]=ifac[0]=1;
for(int i=1; i<=m; ++i) fac[i]=fac[i-1]*i%p,ifac[i]=qp(fac[i],p-2);
for(int i=1; i<=n; ++i) s+=a[i];
int ans=0;
for(int i=1; i<=n; ++i)
{
for(int j=0; j<=1000; ++j) G[b[i]+j]=(G[b[i]+j]+S[j])%p;
++S[b[i]];
}
for(int i=0; i<=2000; ++i) if(G[i]) ans=(ans+G[i]*A(m+i-s+n,n)%p)%p;
printf("%lld\n",ans*qp(C(n,n-2),p-2)%p);
return ;
}
signed main()
{
for(int i=1; i<=n; i++) b[i]=read(),a[i]=(b[i]<<1)-1,--b[i];
if(op) solve1();
else solve0();
return 0;
}