APIO和CTSC一个都去不了太真实了

其实能去才奇怪吧←_←

如果进不了R2还得去APIO似乎更惨一下啊←_←

懵逼的题目

BZOJ

扯淡的 题解

把上面那个题的KMP换成AC自动机就行了

注意因为要"保留贡献"

所以单词的结尾节点在矩阵中要置为1

沙茶的 代码

我居然一遍写对了

/**************************************************************
    Problem: 1444
    User: Cansult
    Language: C++
    Result: Accepted
    Time:796 ms
    Memory:12492 kb
****************************************************************/

// 把那个题的dp改成概率dp是不是就行了
// 一直到当前的影响小于eps?
// 设f[i][j]: 当前已经进行了i次, 在第j个节点, 还未决出胜负的概率
// 对于下一个节点: 如果能结束游戏就结束 然后算出贡献; 否则到f值小于eps时结束
// 还得整矩阵 高消是不存在的

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#define MAXN (100)
#define MAXS (11)
#define DXG (10000000000000ll + 5)
#define LL long long
#define DD double
#define pii pair<int, int>
using namespace std;
struct node {
    int son[MAXS], fail, bh;
} b[MAXN << 5];
struct matrix {
    int n, m;
    DD zh[MAXN][MAXN];
    matrix() { memset(zh, 0, sizeof(zh)); }
} m1, ma, f;
int n, l, m, cntb;
pii mb[MAXN];
char s[MAXN][MAXN];
DD ans[MAXN];
matrix tim(matrix x, matrix y) {
    matrix re;
    re.n = x.n, re.m = y.m;
    for (int i = 0; i < re.n; i++)
        for (int j = 0; j < re.m; j++) 
            for (int k = 0; k < x.m; k++)
                re.zh[i][j] += x.zh[i][k] * y.zh[k][j];
    return re;
}
matrix ksm(LL b) {
    if (!b) return m1;
    matrix re = ksm(b >> 1);
    re = tim(re, re);
    if (b & 1) re = tim(re, ma);
    return re;
}
void initac() {
    queue<int> q;
    for (int i = 0; i < MAXS; i++) if (b[0].son[i]) q.push(b[0].son[i]);
    while (!q.empty()) {
        int dq = q.front();
        q.pop();
        for (int i = 0; i < MAXS; i++)
            if (b[dq].son[i]) b[b[dq].son[i]].fail = b[b[dq].fail].son[i], q.push(b[dq].son[i]);
            else b[dq].son[i] = b[b[dq].fail].son[i];
    }
}
int pd(int x) {
    for (; x; x = b[x].fail)
        if (b[x].bh)
            return b[x].bh;
    return 0;
}
void init() {
    initac();
    m1.n = m1.m = cntb;
    for (int i = 0; i < cntb; i++) m1.zh[i][i] = 1;
    f.n = 1, f.m = cntb;
    f.zh[0][0] = 1;
    ma.n = ma.m = cntb;
    for (int i = 0; i < cntb; i++)
        if (!pd(i))
            for (int j = 0; j < m; j++)
                ma.zh[i][b[i].son[j]] += (DD)mb[j].first / mb[j].second;
        else ma.zh[i][i] = 1; // 就是这个地方 如果不赋为1的话之前的工作就白做了
}
int main() {
    scanf("%d%d%d", &n, &l, &m);
    for (int i = 0; i < m; i++) scanf("%d%d", &mb[i].first, &mb[i].second);
    for (int i = 1; i <= n; i++) {
        scanf("%s", s[i]);
        int dq = 0;
        for (int j = 0, ndq; j < strlen(s[i]); j++) {
            ndq = s[i][j] - 'A';
            if (!b[dq].son[ndq]) b[dq].son[ndq] = ++cntb;
            dq = b[dq].son[ndq];
        }
        b[dq].bh = i;
    }
    ++cntb;
    init();
    f = tim(f, ksm(DXG));
    for (int i = 1; i < cntb; i++) ans[pd(i)] += f.zh[0][i];
    for (int i = 1; i <= n; i++) printf("%.2lf\n", ans[i]);
    return 0;
}

By 准备退役旅游的 Cansult