CF1153F Serval and Bonus Problem
其实这个题很呆,但是考场上沙雕了,看见实数,期望什么的样例还积分,不会就溜了
大致题意:
有一段长为(l)的线段,有(n)个区间,左右端点在([0,l))间均匀随机(可能不是整数)
求期望被至少(k)段区间覆盖的长度,对998244353取膜
其实这个模型很呆,但像我这么sb的第一次看见(可能是忘了)就不会
因为是范围内的实数,那么可以认为没有重合,那么这条线段会被(2n)个端点分成(2n+1)段,因为端点也是随机的,所以每一段期望长度都相同,都是(frac{l}{2n+1})
所以只要对于每一段,计算这一段被至少(k)段区间覆盖的概率
既然算概率当然直接算方案数了,直接dp,设(f[i][j])表示有(i)个端点,第(i)个端点后面的区间被(j)个线段覆盖的方案数。转移直接枚举(i)是一个区间的开始还是结束,如果是结束还要乘(j)转移,表示这个端点可以匹配前面(j)个的任意一个
最后直接枚举合法的方案就行了,记住这个算的是方案数,还要除以(f[2n][0])才是概率。
#include<bits/stdc++.h>
#define il inline
#define vd void
#define mod 998244353
typedef long long ll;
il ll gi(){
ll x=0,f=1;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-')f=-1;
ch=getchar();
}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return x*f;
}
il int pow(int x,int y){
int ret=1;
while(y){
if(y&1)ret=1ll*ret*x%mod;
x=1ll*x*x%mod;y>>=1;
}
return ret;
}
int f[4010][2010],p[2010];
int main(){
#ifdef XZZSB
freopen("in.in","r",stdin);
freopen("out.out","w",stdout);
#endif
int n=gi(),k=gi(),l=1ll*gi()*pow(n<<1|1,mod-2)%mod;
p[0]=1;for(int i=1;i<=n;++i)p[i]=1ll*i*p[i-1]%mod;
f[0][0]=1;
for(int i=0;i<n<<1;++i){
for(int j=std::min(n,i);~j;--j){
f[i+1][j+1]=(f[i+1][j+1]+f[i][j])%mod;
if(j)f[i+1][j-1]=(f[i+1][j-1]+1ll*f[i][j]*j)%mod;
}
}
int ans=0;
for(int i=1;i<=n<<1;++i)
for(int j=k;j<=n;++j)
ans=(ans+1ll*f[i][j]*f[(n<<1)-i][j]%mod*p[j])%mod;
printf("%lld
",1ll*ans*l%mod*pow(f[n<<1][0],mod-2)%mod);
return 0;
}