CF482C Game with Strings
题意
你和你的朋友玩一个游戏,游戏规则如下。
你的朋友创造 n 个长度均为 m 的不相同的字符串,然后他随机地选择其中一个。他选择这些字符串的概率是相等的,也就是说,他选择 n 个字符串中的每一个的概率是 1/n 。你想猜猜你的朋友选择了哪个字符串。
为了猜到你的朋友选择了哪个字符串,你可以问他问题,形式如下:字符串中第 pos 个字符是什么?当问题的答案为唯一标识字符串时,我们认为这个字符串是猜测的。在字符串被猜测后,你将停止提问。
你没有一个特殊的策略,所以你每次可能会等概率的问任何一个你从没提过的位置。你的任务是确定你猜到你的朋友选的字符串所需次数的期望。
输入格式
第一行包括一个数字 n 。接下来 n 行,每行一个字符串,表示你朋友创造出的字符串。除此之外,所有字符的长度是相同的,在1~20之间。
输出格式
输出期望。答案保留九位小数。误差在\(10^-9\)以内.
输入输出样例
输入样例#1:
2
aab
aac
输出样例#1:
2.000000000000000
输入样例#2:
3
aaA
aBa
Caa
输出样例#2:
1.666666666666667
输入样例#3:
3
aca
vac
wqq
输出样例#3:
1.000000000000000
搞了一上午
撞鸭 + 期望
我们预处理出unf[i]表示在状态为i的情况下有哪些串是符合的
unf[i]我们可以通过枚举两个串来计算他们相同的位置
然后我们再从大到小更新unf
我们还可以求出来Num[i]表示在状态为i的情况下有多少串是符合的
f[i] 表示状态为i时距离确定的期望
然后就可以从后向前转移了
状态转移方程\(f[i] = \sum_{j = 1 \&\& (! i | (1 << (j - 1)))}^{n}{\frac{f[i]|1<<(j-1)]}{tot} * \frac{Num[i]|1<<(j-1)}{Num[i]}} + 1\)
tot表示的是状态i中还有多少个位置没问
解释下\(\frac{Num[i||1<<(j-1)}{Num[i]}\)的意思
设\(j = i | (1 << (j - 1)\)
num[j] 一定不大于 num[i]
因为是j向i转移不好考虑
换成i向j转移思考,i有num[j]种选择可以变成j的样子
但是有(num[i]-num[j])的选择是可以直接分辨出答案来的
所以由j向i转移的时候就只需要考虑到那num[j]种情况,所以只有\(num[j]/num[i]\)的概率可以继续转移
余下的\((num[i]-num[j])/num[j]\)就是已经确定的那些
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
# define int long long
const int M = 55 ;
const int N = (1 << 20) + 5 ;
using namespace std ;
int m , n ;
char s[M][M] ;
int unf[N] , Num[N] ;
double f[N] ;
# undef int
int main() {
# define int long long
scanf("%lld",&m) ;
for(int i = 1 ; i <= m ; i ++) scanf("%s",s[i] + 1) ;
n = strlen(s[1] + 1) ;
for(int i = 1 ; i <= m ; i ++)
for(int j = i + 1 , sit ; j <= m ; j ++) {
sit = 0 ;
for(int k = 1 ; k <= n ; k ++)
if(s[i][k] == s[j][k])
sit |= (1LL << (k - 1)) ;
unf[sit] |= (1LL << (i - 1)) ;
unf[sit] |= (1LL << (j - 1)) ;
}
for(int i = (1 << n) - 1 ; i >= 1 ; i --)
for(int j = 1 ; j <= n ; j ++)
if(i & (1 << (j - 1)))
unf[i ^ (1 << (j - 1))] |= unf[i] ;
for(int i = 0 ; i < (1 << n) ; i ++)
for(int j = 1 ; j <= m ; j ++)
if(unf[i] & (1LL << (j - 1)))
Num[i] ++ ;
for(int i = (1 << n) - 2 , tot ; i >= 0 ; i --) {
if(!Num[i]) continue ;
tot = n ;
for(int j = 1 ; j <= n ; j ++)
if(i & (1 << (j - 1))) --tot ;
for(int j = 1 ; j <= n ; j ++) {
if(i & (1 << (j - 1))) continue ;
f[i] += f[i | (1 << (j - 1))] / (double)tot * ((double)Num[i | (1 << (j - 1))] / (double)Num[i]) ;
}
f[i] += 1.0 ;
}
printf("%.10lf\n",f[0]) ;
return 0 ;
}
CF482C Game with Strings的更多相关文章
- CF482C Game with Strings (状压DP+期望DP)
题目大意:甲和乙玩游戏,甲给出n(n<=50)个等长的字符串(len<=20),然后甲选出其中一个字符串,乙随机询问该字符串某一位的字符(不会重复询问一个位置),求乙能确定该串是哪个字符串 ...
- Hacker Rank: Two Strings - thinking in C# 15+ ways
March 18, 2016 Problem statement: https://www.hackerrank.com/challenges/two-strings/submissions/code ...
- StackOverFlow排错翻译 - Python字符串替换: How do I replace everything between two strings without replacing the strings?
StackOverFlow排错翻译 - Python字符串替换: How do I replace everything between two strings without replacing t ...
- Multiply Strings
Given two numbers represented as strings, return multiplication of the numbers as a string. Note: Th ...
- [LeetCode] Add Strings 字符串相加
Given two non-negative numbers num1 and num2 represented as string, return the sum of num1 and num2. ...
- [LeetCode] Encode and Decode Strings 加码解码字符串
Design an algorithm to encode a list of strings to a string. The encoded string is then sent over th ...
- [LeetCode] Group Shifted Strings 群组偏移字符串
Given a string, we can "shift" each of its letter to its successive letter, for example: & ...
- [LeetCode] Isomorphic Strings 同构字符串
Given two strings s and t, determine if they are isomorphic. Two strings are isomorphic if the chara ...
- [LeetCode] Multiply Strings 字符串相乘
Given two numbers represented as strings, return multiplication of the numbers as a string. Note: Th ...
随机推荐
- mysql 判断索引是否存在,存在则删除再创建索引(分表) 存储过程
1.分表5数据量大,执行所有分表修改,不包括5 CREATE PROCEDURE deleteIndex()BEGINDECLARE corpId CHAR (16);DECLARE flag INT ...
- noip模拟赛 写代码
分析:这其实就是括号匹配题,一眼贪心题,不过一开始贪错了,以为([)]是合法的......其实括号之间不能嵌套. 一开始的想法是尽量往左边填左括号,因为每种括号的数量都确定了,那么左括号和右括号的数量 ...
- 「CodePlus 2017 12 月赛」火锅盛宴
n<=100000种食物,给每个食物煮熟时间,有q<=500000个操作:在某时刻插入某个食物:查询熟食中编号最小的并删除之:查询是否有编号为id的食物,如果有查询是否有编号为id的熟食, ...
- POJ 2431 Expedition【贪心】
题意: 卡车每走一个单元消耗一升汽油,中途有加油站,可以进行加油,问能否到达终点,求最少加油次数. 分析: 优先队列+贪心 代码: #include<iostream> #include& ...
- [bzoj4300]绝世好题_二进制拆分
绝世好题 bzoj-4300 题目大意:题目链接. 注释:略. 想法: 二进制拆分然后用一个数组单独存一下当前答案即可. Code: #include <iostream> #includ ...
- HDU——2647 Reward
Reward Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Sub ...
- Ubuntu 16.04出现:"Failed to start /etc/rc.local Compatibility"的问题解决思路
"Failed to start /etc/rc.local Compatibility"这个错误没有最终解决方法,之后思路,如下: 1.打开/etc/rc.local看是否有其它 ...
- Android 原生开发、H5、React-Native使用利弊和场景技术分享
http://m.blog.csdn.net/article/details?id=51778086 发表于2016/6/28 18:52:46 1176人阅读 最近工作中接触到React ...
- JFinal Weixin 微信极速 SDK
原文:https://git.oschina.net/jfinal/jfinal-weixin
- poj 2318 TOYS & poj 2398 Toy Storage (叉积)
链接:poj 2318 题意:有一个矩形盒子,盒子里有一些木块线段.而且这些线段坐标是依照顺序给出的. 有n条线段,把盒子分层了n+1个区域,然后有m个玩具.这m个玩具的坐标是已知的,问最后每一个区域 ...