CF1153F Serval and Bonus Problem

Posted autoint

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF1153F Serval and Bonus Problem相关的知识,希望对你有一定的参考价值。

Serval and Bonus Problem

给?个?度为 (l) 的线段,随机选了 (n) 条?线段,求被覆盖了至少 (k) 次的期望?度。

(1≤k≤n≤2000)

计数DP

https://jkloverdcoi.github.io/2019/04/16/CF1153/

随便在线段上钦定 (2n) 个点,分割成 (2n+1) 段区间,所以每段区间的期望长度就是 (frac l {2n+1})。于是只需要再乘上一段区间至少被 (k) 条线段覆盖的概率就好了。

(f(i,j)) 表示考虑 (i) 个端点,第 (i) 个端点后面的区间恰好被 (j) 条线段所覆盖的方案数。转移时枚举 (i) 是作为左端点还是右端点,(O(n^2)) 大力转移。

最后将所有合法方案数目求和,除以 (f(2n,0)) 得到概率。

统计答案时枚举各个区间的贡献,注意两边的DP组合起来的时候需要乘以 (j!),表示线段端点的对应关系。

CO int N=4000+10;
int fac[N];
int dp[N][N];
 
int main(){
    int n=read<int>(),K=read<int>(),L=read<int>();
    L=mul(L,fpow(2*n+1,mod-2));
    fac[0]=1;
    for(int i=1;i<=n;++i) fac[i]=mul(fac[i-1],i);
    dp[0][0]=1;
    for(int i=0;i<2*n;++i)
        for(int j=n<i?n:i;j>=0;--j){
            dp[i+1][j+1]=add(dp[i+1][j+1],dp[i][j]);
            if(j) dp[i+1][j-1]=add(dp[i+1][j-1],mul(dp[i][j],j));
        }
    int ans=0;
    for(int i=1;i<2*n;++i)
        for(int j=K;j<=n;++j){
            int sum=mul(dp[i][j],dp[2*n-i][j]);
            sum=mul(sum,fac[j]); // corresponding relationship
            ans=add(ans,sum);
        }
    ans=mul(ans,mul(L,fpow(dp[2*n][0],mod-2)));
    printf("%d
",ans);
    return 0;
}

微积分

从另一种角度考虑,恰好 (k) 次的期望长度为
[ l imes int_0^1 (2x(1-x))^k (1-2x(1-x))^{n-k} dx ]

(k)(→k+1) 次只需要乘上一个二次的,除以一个二次的。每次直接积分即可。

我发现积分的结果还要乘上 (inom{n}{k}),这可能是因为线段其实是有放入的先后顺序的,即可以把它看成有标号的。

DP的做法应该是钦定了放入顺序就是从左到右。

poly operator*(CO poly&a,CO poly&b){
    int n=a.size()-1,m=b.size()-1;
    poly ans(n+m+1);
    for(int i=0;i<=n;++i)for(int j=0;j<=m;++j)
        ans[i+j]=add(ans[i+j],mul(a[i],b[j]));
    return ans;
}
poly operator/(poly a,CO poly&b){
    int n=a.size()-1,m=b.size()-1;
    poly ans(n-m+1);
    for(int i=n;i>=m;--i)if(a[i]){
        ans[i-m]=mul(a[i],fpow(b[m],mod-2));
        for(int j=i;j>=i-m;--j) a[j]=add(a[j],mod-mul(ans[i-m],b[j-(i-m)]));
    }
    return ans;
}

CO int N=4000+10;
int inv[N];

poly inter(CO poly&a){
    int n=a.size()-1;
    poly ans(n+2);
    for(int i=1;i<=n+1;++i) ans[i]=mul(a[i-1],inv[i]);
    return ans;
}
int calc(CO poly&a,int x){
    int n=a.size()-1,ans=0;
    for(int i=n;i>=0;--i) ans=add(mul(ans,x),a[i]);
    return ans;
}

CO poly a=(poly){0,2,mod-2},b=(poly){1,mod-2,2};
int fac[N],ifac[N];

IN int binom(int n,int m){
    return mul(fac[n],mul(ifac[m],ifac[n-m]));
}
int main(){
//  freopen("CF1153F.in","r",stdin);
    int n=read<int>();
    inv[0]=inv[1]=1;
    for(int i=2;i<=2*n+1;++i) inv[i]=mul(mod-mod/i,inv[mod%i]);
    fac[0]=1;
    for(int i=1;i<=n;++i) fac[i]=mul(fac[i-1],i);
    ifac[n]=fpow(fac[n],mod-2);
    for(int i=n-1;i>=0;--i) ifac[i]=mul(ifac[i+1],i+1);
    int K=read<int>(),L=read<int>();
    poly f=(poly){1};
    for(int i=1;i<=K;++i) f=f*a;
    for(int i=1;i<=n-K;++i) f=f*b;
    int ans=0;
    for(int i=K;i<=n;++i){
        poly g=inter(f);
        ans=add(ans,mul(calc(g,1),binom(n,i)));
        f=f/b*a;
    }
    ans=mul(ans,L);
    printf("%d
",ans);
    return 0;
}

很遗憾我的代码会TLE。

以上是关于CF1153F Serval and Bonus Problem的主要内容,如果未能解决你的问题,请参考以下文章

CF1153F Serval and Bonus Problem [积分,期望]

Codeforces1153F Serval and Bonus Problem 组合数

CF1153C Serval and Parenthesis Sequence

CF1153C. Serval and Parenthesis Sequence

CF1153D Serval and Rooted Tree

cf-Round551-Div2-D. Serval and Rooted Tree(DP)