[HDU5955]Guessing the Dice Roll
Problem Description
There are N players playing a guessing game. Each player guesses a sequence consists of {1,2,3,4,5,6} with length L, then a dice will be rolled again and again and the roll out sequence will be recorded. The player whose guessing sequence first matches the last L rolls of the dice wins the game.
Input
The
first line is the number of test cases. For each test case, the first
line contains 2 integers N (1 ≤ N ≤ 10) and L (1 ≤ L ≤ 10). Each of the
following N lines contains a guessing sequence with length L. It is
guaranteed that the guessing sequences are consist of {1,2,3,4,5,6} and
all the guessing sequences are distinct.
Output
For each test case, output a line containing the winning probability of each player with the precision of 6 digits.
Sample Input
3
5 1
1
2
3
4
5
6 2
1 1
2 1
3 1
4 1
5 1
6 1
4 3
1 2 3
2 3 4
3 4 5
4 5 6
Sample Output
0.200000 0.200000 0.200000 0.200000
0.200000
0.027778 0.194444 0.194444 0.194444
0.194444 0.194444
0.285337 0.237781 0.237781 0.239102
对所有串建AC自动机,然后按照Trie图建立递推关系,转化成矩阵,用高斯消元解决带环的转移。
写起来略恶心,反正我是不想调了。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <cmath> using namespace std; #define reg register inline int read() { int res = 0;char ch=getchar();bool fu=0; while(!isdigit(ch))fu|=(ch=='-'),ch=getchar(); while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48),ch=getchar(); return fu?-res:res; } int T; int n, L; int nxt[105][7], fail[105], danger[105], tot, who[105]; inline void ins(int *s, int id) { int now = 0; for (reg int i = 1 ; i <= L ; i ++) now = nxt[now][s[i]] ? nxt[now][s[i]] : nxt[now][s[i]] = ++tot; danger[now] = 1; who[now] = id; } inline void Build() { queue <int> q; for (reg int i = 1 ; i <= 6 ;i ++) if (nxt[0][i]) q.push(nxt[0][i]); while(!q.empty()) { int x = q.front();q.pop(); for (reg int i = 1 ; i <= 6 ; i ++) if (nxt[x][i]) fail[nxt[x][i]] = nxt[fail[x]][i], q.push(nxt[x][i]); else nxt[x][i] = nxt[fail[x]][i]; danger[x] |= danger[fail[x]]; } } long double a[105][105], ans[15]; inline void Gauss() { for (reg int i = 0 ; i <= tot ; i ++) { int k = i; for (reg int j = i ; j <= tot ; j ++) if (fabs(a[j][i]) > fabs(a[k][i])) k = j; if (k != i) swap(a[k], a[i]); for (reg int j = 0 ; j <= tot ; j ++) { if (i == j) continue; long double r = a[j][i] / a[i][i]; for (reg int k = i ; k <= tot + 1 ; k ++) a[j][k] -= a[i][k] * r; } } } int main() { T = read(); while(T--) { memset(nxt, 0, sizeof nxt); memset(fail, 0, sizeof fail); memset(danger, 0, sizeof danger); tot = 0; n = read(), L = read(); int tmp[13]; for (reg int i = 1 ; i <= n ; i ++) { for (reg int j = 1 ; j <= L ; j ++) tmp[j] = read(); ins(tmp, i); } Build(); memset(a, 0, sizeof a); for (reg int i = 0 ; i <= tot ; i ++) { a[i][i] -= 1.0; if (danger[i]) continue; for (reg int j = 1 ; j <= 6 ; j ++) a[nxt[i][j]][i] += 1.0 / 6.0; } a[0][tot + 1] = -1.0; // for(int i=0;i<=tot;i++,puts("")) // for(int j=0;j<=tot+1;j++) printf("%.2Lf ",a[i][j]); Gauss(); for (reg int i = 0 ; i <= tot ; i ++) if (danger[i]) ans[who[i]] = a[i][tot + 1] / a[i][i]; for (reg int i = 1 ; i < n ; i ++) printf("%.6Lf ", ans[i]); printf("%.6Lf\n", ans[n]); } return 0; }