【JZOJ 3871】无聊的游戏

Description

学校的运动会开始了,体能很菜的小可可没报任何比赛项目,于是和同学们玩一个十分无聊的游戏。
游戏在一个由n*n个方格组成的正方形棋盘上进行,首先在每个方格上均匀随机地填入1到m之间的正整数(每个方格填的数均不同),然后小可可均匀随机地选出k个1到m的数字(可能选的数不在棋盘上),把它们出现在棋盘上的方格涂黑,设有R行被整行涂黑,有C列被整列涂黑,小可可便可以得到2^(R+C)分。
现在小可可想知道他的期望得分是多少,你能帮助他吗?

Solution

2^(R+C),注意一下就可以发现,这是一个2n位的二进制数的全部子集
还有,题目所谓的填数,其实并没有什么用,
很显然最后的答案就等于所有的权值和/总方案数,
而总方案数= Ckm
gR,C ,R,C是两个集合,表示它的子集的个数,
fR,C ,R,C是两个集合,表示有多少种选数的方案可以达到有R,C这两个集合的状态,

Ans=fR,CgR,CCkm

把最后除的数先不管,

显然,f和g的值只与R和C中为1的个数有关,
转化一下,只要计算 gr,c fr,c (有r列、c行是满的)即可
再转化一下,计算每一个r,c在答案中被计算了多少次,发现f,g其实可以合并:

Ans=r=0nc=0nCrnCcnCktmt

t表示一定要选t个才能达到r,c这个状态,最后一项恰好包含了f,g这两个,

PS:本题可以用C++的double跑过,不要问我为什么。

Code

#include <cstdio>
#include <cstdlib>
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
typedef long double db;
const int N=1e5+50;
int m,n,K;
db C[350],ans,d[N];
int main()
{
    scanf("%d%d%d",&n,&m,&K);
    C[0]=1;fo(i,1,n)C[i]=C[i-1]*(db)(n-i+1)/(db)i;
    d[0]=1;d[1]=1.0*K/m;fo(i,2,K)d[i]=d[i-1]*(db)(K-i+1)/(db)(m-i+1);
    fo(i,0,n)fo(j,0,n)ans+=C[i]*C[j]*d[(i+j)*n-i*j];
    if(ans>1e99)ans=1e99;
    printf("%.9lf\n",(double)ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值