Description

Input

Output

一般概率题有两种套路:

  1. 满足条件的方案/总方案.
  2. 直接求概率.
第一种方法比较好理解,这道题这么做的话也非常简单.
这里讲一下第二种方法:
易得箱子之间都是环的关系,令 $f[i][j]$ 表示一共开了 $j$ 个箱子并成功打开前 $i$ 个环的概率. 
则 $f[i][j+p]+=\frac{f[i-1][j]\times C^{j}_{sum[i-1]}\times C^{p}_{c_{i}}} {C_{sum[i]}^{j+p}}$        
我们强制给第 $i$ 个环分配 $p$ 个箱子,那么产生这种情况的概率是 $\frac{C^{j}_{sum[i-1]}\times C^{p}_{c_{i}}} {C_{sum[i]}^{j+p}}$,而还需满足前 $i-1$ 个箱子也被打开,那么这个概率就是 $f[i-1][j]$,这两个相乘就是发生当前局面的概率. 
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#define setIO(s) freopen(s".in","r",stdin)
#define N 307
using namespace std;
double fac[N],f[N][N];
bool vis[N];
int cir[N],sum[N],a[N];
inline void calc()
{
int n,k,i,j,tot=0,p;
scanf("%d%d",&n,&k);
memset(vis,0,sizeof(vis));
memset(f,0,sizeof(f));
for(i=1;i<=n;++i) scanf("%d",&a[i]), fac[i]=fac[i-1]+log(i);
for(i=1;i<=n;++i)
{
if(vis[i]) continue;
cir[++tot]=0;
for(j=i;!vis[j];j=a[j]) vis[j]=1,cir[tot]++;
}
sum[0]=0,f[0][0]=1.0000;
for(i=1;i<=tot;++i) sum[i]=sum[i-1]+cir[i];
for(i=1;i<=tot;++i)
for(j=i-1;j<k&&j<=sum[i-1];++j)
for(p=1;p<=cir[i]&&j+p<=k;++p)
{
double tmp=exp(fac[sum[i-1]]+fac[cir[i]]+fac[j+p]+fac[sum[i]-j-p]-fac[j]-fac[sum[i-1]-j]-fac[p]-fac[cir[i]-p]-fac[sum[i]]);
f[i][j+p]+=f[i-1][j]*tmp;
}
printf("%.9f\n",f[tot][k]);
}
int main()
{
// setIO("input");
int T,i,j;
scanf("%d",&T);
for(i=1;i<=T;++i) calc();
return 0;
}

  

BZOJ 5004: 开锁魔法II 期望 + 组合的更多相关文章

  1. BZOJ 5004: 开锁魔法II

    比较显然 #include<cstdio> #include<algorithm> #include<cstring> using namespace std; i ...

  2. bzoj5003: 与链 5004: 开锁魔法II 5005:乒乓游戏

    www.lydsy.com/JudgeOnline/upload/task.pdf 第一题题意可以转为选一个长度k的序列,每一项二进制的1的位置被下一项包含,且总和为1,考虑每个二进制位的出现位置,可 ...

  3. 【bzoj5004】开锁魔法II 组合数学+概率dp

    题目描述 有 $n$ 个箱子,每个箱子里有且仅有一把钥匙,每个箱子有且仅有一把钥匙可以将其打开.现在随机打开 $m$ 个箱子,求能够将所有箱子打开的概率. 题解 组合数学+概率dp 题目约定了每个点的 ...

  4. hrb——开锁魔法I——————【规律】

    解题思路:从1到n的倒数之和. #include<stdio.h> #include<string.h> #include<algorithm> using nam ...

  5. hihocoder1075【开锁魔法】

    hihocoder1075[开锁魔法] 题意是给你一个 \(1-n\) 的置换,求选 \(k\) 个可以遍历所有点的概率. 题目可以换个模型:有 \(n\) 个球,有 \(cnt\) 种不同的颜色,求 ...

  6. HihoCoder 1075 开锁魔法III(概率DP+组合)

    描述 一日,崔克茜来到小马镇表演魔法. 其中有一个节目是开锁咒:舞台上有 n 个盒子,每个盒子中有一把钥匙,对于每个盒子而言有且仅有一把钥匙能打开它.初始时,崔克茜将会随机地选择 k 个盒子用魔法将它 ...

  7. hihocoder 1075 : 开锁魔法III

    描述 一日,崔克茜来到小马镇表演魔法. 其中有一个节目是开锁咒:舞台上有 n 个盒子,每个盒子中有一把钥匙,对于每个盒子而言有且仅有一把钥匙能打开它.初始时,崔克茜将会随机地选择 k 个盒子用魔法将它 ...

  8. #1075 : 开锁魔法III

    描述 一日,崔克茜来到小马镇表演魔法. 其中有一个节目是开锁咒:舞台上有 n 个盒子,每个盒子中有一把钥匙,对于每个盒子而言有且仅有一把钥匙能打开它.初始时,崔克茜将会随机地选择 k 个盒子用魔法将它 ...

  9. Hiho #1075: 开锁魔法III

    Problem Statement 描述 一日,崔克茜来到小马镇表演魔法. 其中有一个节目是开锁咒:舞台上有 n 个盒子,每个盒子中有一把钥匙,对于每个盒子而言有且仅有一把钥匙能打开它.初始时,崔克茜 ...

随机推荐

  1. elasticsearch 冷热数据的读写分离

    步骤 一.冷热分离集群配置 比如三个机器共六个node的es集群. 每个机器上各挂载一个ssd 和 一个sata.每个机器需要启动两个es进程.每个进程对应不同类型的磁盘. 关键配置: node.ma ...

  2. mysql——多表——子查询——示例

    子查询: 子查询是将一个查询语句嵌套在另外一个查询语句中,内层查询语句的查询结果,可以作为外来层查询语句提供查询条件. 因此在特定条件下,一个查询语句的条件,需要另外一个查询语句来获取. 前期准备表: ...

  3. selenium-模拟鼠标

    需要导入的包: from selenium.webdriver import ActionChains 一.模拟鼠标右键 ActionChains(self.driver).context_click ...

  4. Win10成功安装IIS后浏览器打开localhost正确显示的页面

  5. Head First PHP&MySQl第四章代码

    addemail.php <!DOCTYPE html> <html lang="cn" dir="ltr"> <head> ...

  6. sys模块&json模块&pickle模块

    sys模块&json模块&pickle模块 sys模块 一.导入方式 import sys 二.作用 与Python解释器交互 三.模块功能 3.1 经常使用 sys.path #返回 ...

  7. 使用python的kazoo模块连接zookeeper实现最基本的增删改查

    kazoo的官方文档地址:https://kazoo.readthedocs.io/en/latest/index.html #!/usr/bin/env python # -*- coding: u ...

  8. 【Java】 Java多线程(一)

    一.对线程的理解 1.线程概念 线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行 ...

  9. python-ssh-远程服务器+远程docker执行命令

    在python语言中实现远程服务器执行命令+远程dcoker执行命令 def ssh_exec_command(ip, username, password, cmd=None): "&qu ...

  10. python子进程模块subprocess详解

    subprocess--子进程管理器一.subprocess 模块简介subprocess最早是在2.4版本中引入的.subprocess模块用来生成子进程,并可以通过管道连接它们的输入/输出/错误, ...