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. IDEA 双击只选择了一个变量的某部分单词

    1,很多抄袭文章说  在keymap 里搜索 select Word at caret , 鄙视手动抄袭和编写爬虫来 作恶的开发者. 2,自己试了,File菜单 ---->  settings- ...

  2. 执行python程序 出现三部曲

    1.执行一个python程序 ,会产生一个进程 ,然后会在内存生成一份内存空间 先把python解释器代码加载到内存里, python解释器代码就是C语言代码 2. 然后再把 自己写的python文件 ...

  3. 导入已有项目到svn

    版本管理一直是程序员使用频率比较高的一个工具软件.不管你是自己使用还是使用别人提供的svn服务,svn的使用技巧都一个必须掌握的技术.为止小编专门制作了关于svn使用技巧的系列文章.今天我们先来介绍一 ...

  4. 2019JAVA第四次实验报告

    JAVA实验报告 班级 计科二班 学号 20188442 姓名 吴怡君 完成时间 2019/9/29 评分等级 实验四 类的继承 1.实验目的 掌握类的继承方法: 变量的继承和覆盖,方法的继承.重载和 ...

  5. hdoj4507(数位dp)

    题目链接:https://vjudge.net/problem/HDU-4507 题意:定义如果一个整数符合下面3个条件之一,那么我们就说这个整数和7有关—— 1.整数中某一位是7: 2.整数的每一位 ...

  6. MySQL -2- 体系结构-多实例模块

    0.在已创建mysql,port=3306的数据库前提下 需要删除/etc/.my.cnf再做以下操作 cp /etc/my.cnf /etc/my.cnf.3306 1.mkdir -p /u02/ ...

  7. SQL 生成表结构表数据脚本

    数据库右击——>任务——>生成脚本——>选择表 ——>高级——>要编写脚本的数据的类型(架构和数据.仅限架构.仅限数据)

  8. ubuntu 安装 TensorFlow、opencv3 的 tips

    安装tensorflow: 创建tensorflow虚拟环境 conda create -n  tensorflow python=2.7 输入命令查看可用版本的tensorflow-gpu cond ...

  9. golang 反射中调用方法

    反射中调用函数 众所周知,golang中的函数是可以像普通的int.float等类型变量那样作为值的,例如: package main import "fmt" func hell ...

  10. Labeling Balls POJ - 3687 优先队列 + 反向拓扑

    优先队列 + 反向拓扑 //#include<bits/stdc++.h> #include<iostream> #include<cstdio> #include ...