题解2019,4.20模拟赛 (白鼠)

Posted jcnl666

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解2019,4.20模拟赛 (白鼠)相关的知识,希望对你有一定的参考价值。

(Description:)

给出一块巧克力,横着可以切 (h) 刀,竖着可以切 (w) 刀,横着切了 (i) ,竖着切了 (j) 可以得到 ((i+1)*(j+1)) 块巧克力,每次切得代价是巧克力块数,求切 (k) 的期望代价,每次在剩余能切的位置等概率选一个切,答案对 (10^9+7) 取模。

(Sample) (Input:)

2 1 2

(Sample) (Output:)

666666677

$Solution: $

一开始考试的时候没啥子想法,瞎写了一个dp ,状态定的不错,只可惜忘记了他每次的概率也会变换,是要顺便在记一个概率的。。。

(Sol_1:)

正解有一种dp,跟我想法差不多:

(f[i][j]) 表示总共切了 (i) 刀,横着切了 (j) 刀的概率

再记一个 (g[i][j]) 表示总共切 $ i $ 刀,横着切了 (j) 刀的期望。

(Sol_2:)

直接暴力处理出两个数组,一个是总方案数,另一个记总代价。

最后两者直接除一除。

注意逆元和切得位置不同,切得顺序不同都算不同方案。

我只写了第二种方法,代码短,好理解。

#include<cstdio>
#include<iostream>
#define int long long
using namespace std;
int h,w,k,ans,sum;
const int N=5000+5,p=1e9+7;
int f[N][N],g[N][N];
inline int power(int a,int b){
    int ret=1;
    while(b){
        if(b&1) ret=(ret*a)%p;
        a=(a*a)%p;
        b>>=1;
    }
    return ret;
}
signed main(){
    scanf("%lld%lld%lld",&h,&w,&k);
    g[0][0]=1;
    for(int i=1;i<=min(h,k);++i){
        g[i][0]=g[i-1][0]*(h-i+1)%p;
        f[i][0]=f[i-1][0]*(h-i+1)%p;
        f[i][0]=(f[i][0]+(i+1)*g[i][0]%p)%p;
    }
    for(int j=1;j<=min(w,k);++j){
        g[0][j]=g[0][j-1]*(w-j+1)%p;
        f[0][j]=f[0][j-1]*(w-j+1)%p;
        f[0][j]=(f[0][j]+(j+1)*g[0][j]%p)%p;
    }
    for(int i=1;i<=min(h,k);++i) for(int j=1;j<=min(w,k-i);++j){
        g[i][j]=(g[i][j]+g[i-1][j]*(h-i+1)%p)%p;
        g[i][j]=(g[i][j]+g[i][j-1]*(w-j+1)%p)%p;
        f[i][j]=(i+1)*(j+1)%p*g[i][j]%p;
        f[i][j]=(f[i][j]+f[i-1][j]*(h-i+1)%p)%p;
        f[i][j]=(f[i][j]+f[i][j-1]*(w-j+1)%p)%p;
    }
    for(int i=0;i<=h;++i) if(k-i<=w)
        ans=(ans+f[i][k-i])%p,sum=(sum+g[i][k-i])%p;
    printf("%lld
",ans*power(sum,p-2)%p);
    return 0;
}

以上是关于题解2019,4.20模拟赛 (白鼠)的主要内容,如果未能解决你的问题,请参考以下文章

WC2019 全国模拟赛第一场 T1 题解

2019-09-03高一组模拟赛 3 &高二组模拟赛 2 题解

4.20 nanchang 回顾

思维模拟+暴力——icpc nwrrc 2019 K

思维模拟+暴力——icpc nwrrc 2019 K

字节跳动2019春招研发部分编程题汇总题解