zoukankan      html  css  js  c++  java
  • 1444: [Jsoi2009]有趣的游戏

    1444: [Jsoi2009]有趣的游戏

    链接

    分析:

      如果一个点回到0号点,那么会使0号点的概率增加,而0号点的概率本来是1,不能增加,所以这题用期望做。

      设$x_i$表示经过i的期望次数,然后初始可以知道$x_0=0$,又因为末尾节点只会经过一次,所以末尾节点的概率就是期望。

      然后建出AC自动机,高斯消元。

      参考sengxian

    代码:

    Gauss

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #include<cctype>
    #include<set>
    #include<queue>
    #include<vector>
    #include<map>
    using namespace std;
    typedef long long LL;
    
    inline int read() {
        int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
        for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
    }
    
    const int N = 500;
    const double eps = 1e-10;
    int ch[N][26], val[N], fail[N], id[N], q[N], Index;
    int n, L, m;
    char s[N];
    double A[N][N], p[N];
    
    void Insert(int x) {
        int now = 0;
        for (int i = 0; i < L; ++i) {
            int c = s[i] - 'A';
            if (!ch[now][c]) ch[now][c] = ++Index;
            now = ch[now][c];
        }
        val[now] = 1, id[x] = now;
    }
    void bfs() {
        int L = 1, R = 0;
        for (int c = 0; c < m; ++c) if (ch[0][c]) q[++R] = ch[0][c];
        while (L <= R) {
            int u = q[L ++]; 
            for (int c = 0; c < m; ++c) {
                int v = ch[u][c];
                if (!v) ch[u][c] = ch[fail[u]][c];
                else {
                    fail[v] = ch[fail[u]][c];
                    val[v] |= val[fail[v]];
                    q[++R] = v;
                }
            }
        }
    }
    bool Gauss(int n) {
        for (int k = 0; k <= n; ++k) {
            int r = k;
            for (int i = k + 1; i <= n; ++i) if (A[i][k] > A[r][k]) r = k;
            if (r != k) for (int j = 0; j <= n + 1; ++j) swap(A[r][j], A[k][j]);
            for (int i = k + 1; i <= n; ++i) {
                if (fabs(A[i][k]) > eps) {
                    double t = A[i][k] / A[k][k];
                    for (int j = 0; j <= n + 1; ++j) A[i][j] -= A[k][j] * t;
                }
            }
        }
        for (int i = n; i >= 0; --i) {
            for (int j = i + 1; j <= n; ++j) A[i][n + 1] -= A[j][n + 1] * A[i][j];
            A[i][n + 1] /= A[i][i];
        }
        return 1;
    }
    int main() {
        n = read(), L = read(), m = read();
        for (int i = 0; i < m; ++i) {
            int u = read(), v = read();
            p[i] = 1.0 * u / v;
        }
        int cnt = 0;
        for (int i = 0; i < n; ++i) {
            scanf("%s", s);
            for (int j = 0; j < L; ++j) 
                if (p[s[j] - 'A'] <= eps) { cnt ++; break; }
            Insert(i);
        }
        if (cnt == n) {
            for (int i = 1; i <= n; ++i) puts("0.00"); return 0;
        }
        bfs();
        A[0][Index + 1] = -1;
        for (int i = 0; i <= Index; ++i) {
            A[i][i] = -1.0;
            if (val[i]) continue;
            for (int c = 0; c < m; ++c) A[ch[i][c]][i] += p[c];
        }
        Gauss(Index);
        for (int i = 0; i < n; ++i) {
            double p = A[id[i]][Index + 1];
            if (fabs(p) <= eps) puts("0.00");
            else printf("%.2lf
    ", p);
        }
        return 0;
    }
    View Code

    迭代+矩阵

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #include<cctype>
    #include<set>
    #include<queue>
    #include<vector>
    #include<map>
    using namespace std;
    typedef long long LL;
    
    inline int read() {
        int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
        for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
    }
    
    const int N = 105;
    struct Node { 
        double a[N][N]; 
        Node() { memset(a, 0, sizeof(a)); } 
    } A;
    int ch[N][26], val[N], fail[N], id[N], q[N], Index;
    int n, L, m;
    char s[N];
    double p[N];
    
    Node operator * (const Node &A,const Node &B) {
        Node C;
        for (int k = 0; k <= Index; ++k)
            for (int i = 0; i <= Index; ++i)     
                for (int j = 0; j <= Index; ++j) 
                    C.a[i][j] += A.a[i][k] * B.a[k][j];
        return C;
    }
    void Insert(int x) {
        int now = 0;
        for (int i = 0; i < L; ++i) {
            int c = s[i] - 'A';
            if (!ch[now][c]) ch[now][c] = ++Index;
            now = ch[now][c];
        }
        val[now] = 1, id[x] = now;
    }
    void bfs() {
        int L = 1, R = 0;
        for (int c = 0; c < m; ++c) if (ch[0][c]) q[++R] = ch[0][c];
        while (L <= R) {
            int u = q[L ++]; 
            for (int c = 0; c < m; ++c) {
                int v = ch[u][c];
                if (!v) ch[u][c] = ch[fail[u]][c];
                else {
                    fail[v] = ch[fail[u]][c];
                    val[v] |= val[fail[v]];
                    q[++R] = v;
                }
            }
        }
    }
    int main() {
        n = read(), L = read(), m = read();
        for (int i = 0; i < m; ++i) {
            int u = read(), v = read();
            p[i] = 1.0 * u / v;
        }
        for (int i = 0; i < n; ++i) {
            scanf("%s", s);
            Insert(i);
        }
        bfs();
        for (int i = 0; i <= Index; ++i) {
            if (val[i]) A.a[i][i] = 1;
            else for (int c = 0; c < m; ++c) A.a[i][ch[i][c]] += p[c];
        }
        for (int i = 1; i <= 50; ++i) A = A * A;
        for (int i = 0; i < n; ++i) printf("%.2lf
    ", A.a[0][id[i]]);
        return 0;
    }
    View Code
  • 相关阅读:
    【二分图最大独立集/最小割】P3355 骑士共存问题
    【费用流+正负费用处理】UVA11613 Acme Corporation
    【费用流】P2517 [HAOI2010]订货
    【最小割】P1361 小M的作物
    【最小割】[SHOI2007]善意的投票
    【最小割+割点转换】[USACO5.4]奶牛的电信Telecowmunication
    数据结构学习笔记——ST表
    图论学习笔记——LCA
    基于CNN的手写数字识别程序
    [Atcoder]M-Solutions 题解
  • 原文地址:https://www.cnblogs.com/mjtcn/p/10389148.html
Copyright © 2011-2022 走看看