HDU 5955 Guessing the Dice Roll
HDU 5955 Guessing the Dice Roll
2016 ACM/ICPC 亚洲区沈阳站
题意
- 有\(N\le 10\)个人,每个猜一个长度为\(L \le 10\)的由\(1-6\)构成的序列,保证序列两两不同。
- 不断地掷骰子,直到后缀与某人的序列匹配,则对应的人获胜。
- 求每个人获胜的概率。
思路
- 显然,涉及的序列最多100个,用ac自动机构出这些状态,计算状态之间的转移概率。
- 记增量矩阵为\(A\)(即终状态不再计算转移到自身的概率),答案为\(b\),初始序列为\(x\),则$$b=\sum_{i=1}{\infty}{Ai}x$$
- 显然矩阵\(A\)是收敛的,所以式子转化为$$b=(I-A)^{-1}x\x=(I-A)b$$
- 高斯消元求解即可,注意精度问题。
- 另一种解法,构造包括终止状态转移到自身的矩阵,结合快速幂,可以卡过去(注意指数取\(2^i\)形式以减少常数)。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define sz(x) ((int)(x).size())
#define rep(i,l,r) for(int i=(l);i<(r);++i)
//-------head-------
const int N = 1007;
const double EPS = 1e-12;
int n, l, a[N], id[N];
template<int V>
struct AhoCorasick {
int dep[V];
int siz, lnk[V], que[V], trie[V][7];
int addNode(int _dep) {
memset(trie[siz], 0, sizeof(trie[siz]));
lnk[siz] = 0, dep[siz] = _dep;
return siz++;
}
void init() {
siz = 0;
addNode(0);
}
int add(const int *a, int n) {
int p = 0;
rep(i, 0, n)
{
int x = a[i];
if (!trie[p][x])
trie[p][x] = addNode(i + 1);
p = trie[p][x];
}
return p;
}
void build() {
que[0] = 0;
for (int h = 0, t = 1; h < t; ++h) {
int v = que[h];
rep(c, 1, 7)
if (trie[v][c]) {
int u = lnk[v];
while (u && !trie[u][c])
u = lnk[u];
lnk[trie[v][c]] = !v ? 0 : trie[u][c];
que[t++] = trie[v][c];
} else {
trie[v][c] = trie[lnk[v]][c];
}
}
}
};
template<int N>
struct Gauss {
double a[N][N];
void init(int n, int m) {
rep(i, 0, n)
rep(j, 0, m)
a[i][j] = 0;
}
void run(int n, int m) {
int row, col;
for (row = col = 0; row < n && col < m; ++row, ++col) {
int mxr = row;
rep(i, row + 1, n)
if (fabs(a[i][col]) > fabs(a[mxr][col]))
mxr = i;
if (fabs(a[mxr][col]) < EPS) {
--row;
continue;
}
if (mxr != row)
swap(a[row], a[mxr]), swap(id[row], id[mxr]);
rep(i, 0, n)
if (i != row && fabs(a[i][col]) > EPS)
for (int j = m; j >= col; --j)
a[i][j] -= a[row][j] * a[i][col] / a[row][col];
}
}
void out(int n, int m) {
rep(i, 0, n) {
rep(j, 0, m)
printf("%lf ", a[i][j]);
puts("");
}
}
};
AhoCorasick<N> ac;
Gauss<N> ga;
double ans[N];
int main() {
int T;
scanf("%d", &T);
rep(cas, 0, T) {
scanf("%d%d", &n, &l);
ac.init();
memset(id, -1, sizeof(id));
rep(i, 0, n) {
rep(j, 0, l)
scanf("%d", &a[j]);
id[ac.add(a, l)] = i;
}
ac.build();
ga.init(ac.siz, ac.siz + 1);
rep(i, 0, ac.siz) {
if (~id[i]) {
// ga.a[i][i] = 0;
} else {
rep(j, 1, 7)
ga.a[ac.trie[i][j]][i] += 1.0 / 6.0 ;
}
}
rep(i, 0, ac.siz)
ga.a[i][i] -= 1.0;
ga.a[0][ac.siz] = -1.0;
// ga.out(ac.siz, ac.siz + 1);
ga.run(ac.siz, ac.siz);
// puts("");
// ga.out(ac.siz, ac.siz + 1);
rep(i, 0, ac.siz)
if (~id[i]) {
ans[id[i]] = ga.a[i][ac.siz] / ga.a[i][i];
}
rep(i, 0, n) {
if (i)
putchar(' ');
printf("%.6lf", fabs(ans[i]));
}
puts("");
}
return 0;
}
HDU 5955 Guessing the Dice Roll的更多相关文章
- hdu 5955 Guessing the Dice Roll 【AC自动机+高斯消元】
hdu 5955 Guessing the Dice Roll [AC自动机+高斯消元] 题意:给出 n≤10 个长为 L≤10 的串,每次丢一个骰子,先出现的串赢,问获胜概率. 题解:裸的AC自动机 ...
- HDU 5966 Guessing the Dice Roll
题意有 N≤10 个人,每个猜一个长度为L≤10的由1−6构成的序列,保证序列两两不同.不断地掷骰子,直到后缀与某人的序列匹配,则对应的人获胜.求每个人获胜的概率. 思路:建立trie图,跑高斯消元. ...
- hdu5955 Guessing the Dice Roll【AC自动机】【高斯消元】【概率】
含高斯消元模板 2016沈阳区域赛http://acm.hdu.edu.cn/showproblem.php?pid=5955 Guessing the Dice Roll Time Limit: 2 ...
- 2016ACM/ICPC亚洲区沈阳站H - Guessing the Dice Roll HDU - 5955 ac自动机+概率dp+高斯消元
http://acm.hdu.edu.cn/showproblem.php?pid=5955 题意:给你长度为l的n组数,每个数1-6,每次扔色子,问你每个串第一次被匹配的概率是多少 题解:先建成ac ...
- [HDU5955]Guessing the Dice Roll
Problem Description There are N players playing a guessing game. Each player guesses a sequence cons ...
- 【HDU5955】Guessing the Dice Roll/马尔科夫
先从阿里机器学习算法岗网络笔试题说起:甲乙两人进行一个猜硬币的游戏.每个人有一个目标序列,由裁判来抛硬币.谁先得到裁判抛出的一串连续结果,谁赢. 甲的目标序列是正正正,乙的目标序列是反正正.那么如果裁 ...
- 【AC自动机】【高斯消元】hdu5955 Guessing the Dice Roll
http://blog.csdn.net/viphong/article/details/53098489 我有一点不是很懂,这样算出来转移到AC自动机根节点的概率是一个远大于1的数. 按我的理解,因 ...
- 【HDOJ5955】Guessing the Dice Roll(概率DP,AC自动机,高斯消元)
题意: 有n个人,每个人有一个长为L的由1~6组成的数串,现在扔一个骰子,依次记录扔出的数字,如果当前扔出的最后L个数字与某个人的数串匹配,那么这个人就算获胜,现在问每个人获胜的概率是多少. n,l& ...
- hdu 4586 Play the Dice 概率推导题
A - Play the DiceTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/contest/ ...
随机推荐
- bzoj 1185 旋转卡壳 最小矩形覆盖
题目大意 就是求一个最小矩形覆盖,逆时针输出其上面的点 这里可以看出,那个最小的矩形覆盖必然有一条边经过其中凸包上的两个点,另外三条边必然至少经过其中一个点,而这样的每一个点逆时针走一遍都满足单调性 ...
- monkey(1)
写完应用之后,作完单元测试和功能测试,必要对应用的抗打击能力做个测试,最好的方法是雇个“猴子”在测试,猴子可以胡乱瞎按键,在这种情况下,你的应用是否还能正常工作呢?Android 测试包中提供了一个M ...
- [转]AndroidManifest.xml文件详解
转自:http://www.cnblogs.com/greatverve/archive/2012/05/08/AndroidManifest-xml.html AndroidManifest.xml ...
- jQuery 常用动画
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- 《hanoi(汉诺塔)问题》求解
//Hanoi(汉诺)塔问题.这是一个古典的数学问题,用递归方法求解.问题如下: /* 古代有一个梵塔,塔内有3个座A,B,C,开始时A座上有64个盘子,盘子大小不等,大的在下,小的在上. 有一个老和 ...
- org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
最近在项目中发现如下异常: 六月 25, 2015 5:58:34 下午 org.apache.catalina.core.StandardWrapperValve invoke严重: Servlet ...
- (转)关于java和web项目中的相对路径问题
原文:http://blog.csdn.net/yethyeth/article/details/1623283 关于java和web项目中的相对路径问题 分类: java 2007-05-23 22 ...
- 对NSNumber的理解
1.nsnumber最重要的作用是可以封装任何的值对象,就是说nsnumber对象的类型可以是任何的类型. 如nsnumber *number = @"12" nsnumber * ...
- FR #2题解
A. 考虑把(u,v)的询问离线挂在u上,然后dfs,每次从fath[x]到[x]相当于x子树dis区间加1,x子树以外区间-1,然后维护区间和区间平方和等. 常数略大. #include<io ...
- PHP中常用正则表达式大全
常用正则表达式大全!(例如:匹配中文.匹配html) 匹配中文字符的正则表达式: [u4e00-u9fa5] 评注:匹配中文还真是个头疼的事,有了这个表达式就好办了 匹配双字节字符(包括汉字在内 ...