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的更多相关文章

  1. hdu 5955 Guessing the Dice Roll 【AC自动机+高斯消元】

    hdu 5955 Guessing the Dice Roll [AC自动机+高斯消元] 题意:给出 n≤10 个长为 L≤10 的串,每次丢一个骰子,先出现的串赢,问获胜概率. 题解:裸的AC自动机 ...

  2. HDU 5966 Guessing the Dice Roll

    题意有 N≤10 个人,每个猜一个长度为L≤10的由1−6构成的序列,保证序列两两不同.不断地掷骰子,直到后缀与某人的序列匹配,则对应的人获胜.求每个人获胜的概率. 思路:建立trie图,跑高斯消元. ...

  3. hdu5955 Guessing the Dice Roll【AC自动机】【高斯消元】【概率】

    含高斯消元模板 2016沈阳区域赛http://acm.hdu.edu.cn/showproblem.php?pid=5955 Guessing the Dice Roll Time Limit: 2 ...

  4. 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 ...

  5. [HDU5955]Guessing the Dice Roll

    Problem Description There are N players playing a guessing game. Each player guesses a sequence cons ...

  6. 【HDU5955】Guessing the Dice Roll/马尔科夫

    先从阿里机器学习算法岗网络笔试题说起:甲乙两人进行一个猜硬币的游戏.每个人有一个目标序列,由裁判来抛硬币.谁先得到裁判抛出的一串连续结果,谁赢. 甲的目标序列是正正正,乙的目标序列是反正正.那么如果裁 ...

  7. 【AC自动机】【高斯消元】hdu5955 Guessing the Dice Roll

    http://blog.csdn.net/viphong/article/details/53098489 我有一点不是很懂,这样算出来转移到AC自动机根节点的概率是一个远大于1的数. 按我的理解,因 ...

  8. 【HDOJ5955】Guessing the Dice Roll(概率DP,AC自动机,高斯消元)

    题意: 有n个人,每个人有一个长为L的由1~6组成的数串,现在扔一个骰子,依次记录扔出的数字,如果当前扔出的最后L个数字与某个人的数串匹配,那么这个人就算获胜,现在问每个人获胜的概率是多少. n,l& ...

  9. hdu 4586 Play the Dice 概率推导题

    A - Play the DiceTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/contest/ ...

随机推荐

  1. hibernate框架

    在之前的DAO开发中,对关系型数据库进行增删改查都是直接通过sql语句,需要人工的进行对象和表之间的转换.而Hibernate提供了对象和表之间进行映射的框架,使得这种转换更加方便. 1.ORM概念 ...

  2. android 录音的断点续传

    系统没有暂停的功能  只能把每次的录音进行拼接... package com.example.zrecord; import java.io.File;import java.io.FileInput ...

  3. Ubuntu 14.10 下Ganglia监控Hadoop集群

    前提是已经安装好Ganglia和Hadoop集群 1 Master节点配置hadoop-metrics2.properties # syntax: [prefix].[source|sink|jmx] ...

  4. Python学习路程day6

    shelve 模块 shelve模块是一个简单的k,v将内存数据通过文件持久化的模块,可以持久化任何pickle可支持的python数据格式 import shelve d = shelve.open ...

  5. 2013 imac 安装 win7

    昨天晚上安装imac win7系统,其实步骤是很简单的,首先需要一个用boot camp助手做好的win7安装U盘或者有个外接光驱加一张win7光盘,然后用boot camp助理划分一个分区给win7 ...

  6. Fractal Tree扩展

    之前的博客实现了最基础的分形树,在这个基础上略微调整一些参数可以得到很多有趣的由分形树发展出的图案. private void drawShape(Graphics g, double x1, dou ...

  7. Get start with Android development

    Firstly we should install the right version of JDK and JRE, there are two version of ADK for differe ...

  8. Add Two Numbers ---- LeetCode 002

    You are given two linked lists representing two non-negative numbers. The digits are stored in rever ...

  9. XMPP即时通讯

    XMPP:XMPP是基于XML的点对点通讯协议,The Extensible Messaging and Presence Protocol(可扩展通讯和表示协议). XMPP可用于服务类实时通讯,表 ...

  10. 7、网页制作Dreamweaver(悬浮动态分层导航)

    悬浮动态分层导航的制作: 1.首先在<head>里面引用一个JQUERY的文件以用来制作鼠标点击动画效果(从网站上下载即可) <script language="javas ...