CodeForces 457 D.Bingo!(期望)

Description

m 个不同的数字去放到一个n×n的棋盘中,然后随机从这 m 个数中取一个k子集,把棋盘中出现这 k 个数的位置标记,对于这个状态,其得分为2^{被完全标记的行数 + 被完全标记的列数},问得分的期望值,取期望值与1099的较小值输出

Input

三个整数 n,m,k(1n300,n2m105,nkm)

Output

输出得分期望值与 1099 的较小值

Sample Input

1 2 1

Sample Output

2.5

Solution

一状态 sta 被标记行列数和为 f(sta) ,则其对分数总和贡献为 2f(sta) ,而注意到 2f(sta) 为从这些行列集中选出一子集方案数,设状态集为 S ,则得分期望值ans=1|S|staS2f(sta)=1|S|staSr=0nc=0n对于状态 sta 被完全标记的行列中选出 r c列的方案数 =r=0nc=0nCrnCcnpr,c

其中 pr,c 为选出的 r c列被标记的概率,不考虑数字之间的排列,总方案数为 Ckm ,令 z=n(r+c)rc 为这 r c列的格子数,则这 z 个位置必然在选出的k个数中,然后要从剩下的 mz 个数中选出 kz 个数字组成这 k 个数字,方案数Ckzmz,故 pr,c=CkzmzCkm

Code

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int,int>P;
const int INF=0x3f3f3f3f,maxn=100005;
ld f[maxn];
ld C(int n,int m)
{
    return f[n]-f[m]-f[n-m];
}
int main()
{
    f[0]=0;
    for(int i=1;i<=1e5;i++)f[i]=f[i-1]+log(1.0*i);
    int n,m,k;
    scanf("%d%d%d",&n,&m,&k);
    ld ans=0;
    for(int x=0;x<=n;x++)
        for(int y=0;y<=n;y++)
            if(n*(x+y)-x*y<=k)
            {
                int z=n*(x+y)-x*y;
                ld temp=C(n,x)+C(n,y)+C(m-z,k-z)-C(m,k);
                ans=min((ld)1e99,ans+exp(temp));
            }
    printf("%.10f\n",(double)ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值