CF1153F Serval and Bonus Problem

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\n",1ll*ans*l%mod*pow(f[n<<1][0],mod-2)%mod);
    return 0;
}

转载于:https://www.cnblogs.com/xzz_233/p/10706754.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值