【Foreign】开锁 [概率DP]
开锁
Time Limit: 10 Sec Memory Limit: 256 MB
Description

Input

Output

Sample Input
5 1
2 5 4 3 1
5 2
2 5 4 3 1
5 3
2 5 4 3 1
5 4
2 5 4 3 1
Sample Output
0.600000000
0.900000000
1.000000000
HINT

Main idea
一个宝箱内有一个可以开启别的宝箱的钥匙,可以选择k个宝箱,询问能开启所有宝箱的概率。
Solution
我们一看就知道这是一道概率DP的题目。
我们发现,每个宝箱有一个对应的钥匙,那么显然若干个宝箱会构成一个环,只要开了一个环中的一个宝箱就可以开启这个环。
那么我们要求的就是:在n个数中选k次,已知每个环的大小,选中环中的一个元素即视为选中了这个环,问每个环都被至少选了一次的概率。
显然直接记概率不好计算,于是我们可以算出可行的方案数。
我们先求出每个环的大小,然后令 f[i][j] 表示前 i 个环选了 j 个元素的方案数,那么显然可以枚举这一个环中选了几个,那么显然有:

然后我们最后用 f[num][k] / 总方案数 C(n,k) 即可。注意要用double来存,否则数字不够大。
Code
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
using namespace std; const int ONE=; int T,n,k;
int a[ONE],vis[ONE],cnt;
int ring[ONE],num;
int record;
double C[ONE][ONE];
double f[ONE][ONE]; int get()
{
int res=,Q=;char c;
while( (c=getchar())< || c> )
if(c=='-')Q=-;
res=c-;
while( (c=getchar())>= && c<= )
res=res*+c-;
return res*Q;
} void Solve()
{
n=get(); k=get(); for(int i=;i<=n;i++) a[i]=get(),vis[i]=;
num=;
for(int i=;i<=n;i++)
{
if(vis[i]) continue;
int x=i;
cnt=;
for(;;)
{
vis[x]=; x=a[x]; cnt++;
if(x==i) break;
}
ring[++num]=cnt;
} memset(f,,sizeof(f));
f[][]=; record=;
for(int i=;i<=num;i++)
{
record+=ring[i];
for(int j=;j<=record;j++)
{
for(int x=;x<=ring[i] && x<=j;x++)
{
f[i][j] += f[i-][j-x] * C[ring[i]][x];
}
}
} cout<<(double)f[num][k]/C[n][k]<<endl;
} int main()
{
C[][]=;
for(int i=;i<=;i++)
{
C[i][]=;
for(int j=;j<=;j++)
C[i][j]=C[i-][j-]+C[i-][j];
} T=get();
while(T--)
Solve(); }
【Foreign】开锁 [概率DP]的更多相关文章
- HihoCoder 1075 开锁魔法III(概率DP+组合)
描述 一日,崔克茜来到小马镇表演魔法. 其中有一个节目是开锁咒:舞台上有 n 个盒子,每个盒子中有一把钥匙,对于每个盒子而言有且仅有一把钥匙能打开它.初始时,崔克茜将会随机地选择 k 个盒子用魔法将它 ...
- 【bzoj5004】开锁魔法II 组合数学+概率dp
题目描述 有 $n$ 个箱子,每个箱子里有且仅有一把钥匙,每个箱子有且仅有一把钥匙可以将其打开.现在随机打开 $m$ 个箱子,求能够将所有箱子打开的概率. 题解 组合数学+概率dp 题目约定了每个点的 ...
- hihocoder 1075 : 开锁魔法III
描述 一日,崔克茜来到小马镇表演魔法. 其中有一个节目是开锁咒:舞台上有 n 个盒子,每个盒子中有一把钥匙,对于每个盒子而言有且仅有一把钥匙能打开它.初始时,崔克茜将会随机地选择 k 个盒子用魔法将它 ...
- #1075 : 开锁魔法III
描述 一日,崔克茜来到小马镇表演魔法. 其中有一个节目是开锁咒:舞台上有 n 个盒子,每个盒子中有一把钥匙,对于每个盒子而言有且仅有一把钥匙能打开它.初始时,崔克茜将会随机地选择 k 个盒子用魔法将它 ...
- Hiho #1075: 开锁魔法III
Problem Statement 描述 一日,崔克茜来到小马镇表演魔法. 其中有一个节目是开锁咒:舞台上有 n 个盒子,每个盒子中有一把钥匙,对于每个盒子而言有且仅有一把钥匙能打开它.初始时,崔克茜 ...
- 【整理】简单的数学期望和概率DP
数学期望 P=Σ每一种状态*对应的概率. 因为不可能枚举完所有的状态,有时也不可能枚举完,比如抛硬币,有可能一直是正面,etc.在没有接触数学期望时看到数学期望的题可能会觉得很阔怕(因为我高中就是这么 ...
- hihoCode 1075 : 开锁魔法III
时间限制:6000ms 单点时限:1000ms 内存限制:256MB 描述 一日,崔克茜来到小马镇表演魔法. 其中有一个节目是开锁咒:舞台上有 n 个盒子,每个盒子中有一把钥匙,对于每个盒子而言有且仅 ...
- HDU5985 Lucky Coins 概率dp
题意:给你N种硬币,每种硬币有Si个,有Pi 概率朝上,每次抛所有硬币抛起,所有反面的拿掉,问每种硬币成为最后的lucky硬币的概率. 题解:都知道是概率dp,但是模拟赛时思路非常模糊,很纠结,dp[ ...
- 概率dp总结
终于做到概率dp题了,开个总结帖记录一下 首先是几篇论文:有关概率和期望问题的研究 做了这么多题,实际上没什么特别好总结的,就是搞清状态和转移,顺着写就行了,和基本dp差不多 概率是由过去到现在dp[ ...
随机推荐
- CC3200在sl_Start函数处不断重启复位的原因解析
1. 使用过程中,自己写的工程,发现CC3200一直重启,首先需要定位出现重启的函数?看门狗复位,还是程序跑飞复位?NWP的版本不匹配?经过测试找到出问题的函数,这个函数是启动网络的函数. lRetV ...
- Ubuntu下使用Git_4
在这个第四个文章中,我将练习GIT的高级阶段了,由于高级阶段的内容转的比较多,我自己的代码除了我自己可以看懂意外,大家可能看不懂,所以我将会按照 http://git.wiki.navisec.it/ ...
- Zabbix_agentd 启动报错
C:\zabbix>c:\Zabbix\zabbix_agentd.exe -i -c c:\Zabbix\zabbix_agentd.conf zabbix_agentd.exe [1144] ...
- Thymeleaf 使用时的标签
1 . onclick事件 <a th:onclick="'javascript:more()'" ></a> 2.引入CSS样式 <link t ...
- 标准H5文件头的写法
整理代码如下: <!DOCTYPE html> <!-- 声明文档语言属性 --> <!-- 中文 --> <html lang="zh-Hans& ...
- Python中send()和sendall()的区别
Python中send()和sendall()的区别 估计每个学习Python网络编程的人,都会遇到过这样的问题: send()和sendall()到底有什么区别? send()和sendall()原 ...
- Bitcoin-NG
Bitcoin-NG,一个新的可扩展的区块链协议 Bitcoin-NG仅受限于网络的传输延时,它的带宽仅受限于个人节点的处理能力.通过将比特币的区块链操作分解为两部分来实现这个性能改善:首领选择(le ...
- 【SSH】——两种添加jar包方式的比较
[前言] 在开发过程中,我们对Eclipse或MyEclipse等IDE越来越熟悉了.在使用的过程中,小编了解到两种添加jar包的方式,今天给大家说下这两种方式的差别. 方法一: 将所需要的jar包拷 ...
- C++关于堆的函数
建立堆 make_heap(_First, _Last, _Comp) 默认是建立最大堆的.对int类型,可以在第三个参数传入greater<int>()得到最小堆. 在堆中添加数据 ...
- 【python】python中的定义类属性和对像属性
python中变量是没有类型的可以绑定任意类型,但是在语法上不能声明变量. 那我们怎麽来声名一个变量呢? f=None 这样我们给着个变量绑定了以各None类型,我们随时可用重新绑定其它类型.这样我们 ...