2016icpc沈阳 HDU 5955 Guessing the Dice Roll AC自动机 高斯消元

来源:互联网 发布:小学安全网络知识竞赛 编辑:程序博客网 时间:2024/04/27 14:38

题意:n个人每人一个长为L的只包含1-6的猜测序列,一直掷骰子直到结果出现某个人的猜测序列,该人获胜,求每人获胜概率


题解:随机过程里的马尔可夫过程的稳定状态,在AC自动机上做状态转移,

#include <iostream>#include <cstdio>#include <cctype>#include <algorithm>#include <cstring>#include <string>#include <cmath>#include <vector>#include <set>#include <stack>#include <sstream>#include <queue>#include <map>#include <functional>#include <bitset>#include <ctime>using namespace std;#define pb push_back#define mk make_pair#define ll long long#define ull unsigned long long#define pii pair<int, int>#define mk make_pair#define fi first#define se second#define ALL(A) A.begin(), A.end()#define rep(i,n) for(int (i)=0;(i)<(int)(n);(i)++)#define repr(i, n) for(int (i)=(int)(n);(i)>=0;(i)--)#define repab(i,a,b) for(int (i)=(int)(a);(i)<=(int)(b);(i)++)#define reprab(i,a,b) for(int (i)=(int)(a);(i)>=(int)(b);(i)--)#define sc(x) scanf("%d", &x)#define pr(x) printf("x:%d\n", x)#define fastio ios::sync_with_stdio(0), cin.tie(0)#define frein freopen("in.txt", "r", stdin)#define freout freopen("out.txt", "w", stdout)#define freout1 freopen("out1.txt", "w", stdout)#define lb puts("")#define lson ((rt<<1)+1)#define rson ((rt<<1)+2)#define mid ((l+r)/2)#define lmid (l+(r-l)/3)#define rmid (r-(r-l)/3)#define debug cout<<"???"<<endlconst double PI = 3.1415926535897932384626433;const ll mod = 2147493647;const int INF = 0x3f3f3f3f;const double eps = 1e-12;template<class T> T gcd(T a, T b){if(!b)return a;return gcd(b,a%b);}const int maxn = 120, sgm_sz = 6;struct Trie{    int ch[maxn][sgm_sz];    int val[maxn];    int last[maxn];    int f[maxn];    int val_id[maxn];    int sz;    void init()    {        sz = 1;        memset(ch[0], 0, sizeof(ch[0]));        memset(val_id, 0, sizeof(val_id));    }    int idx(char c) {return c - '1';}    void Insert(char *s, int v)    {        int u = 0, len = strlen(s);        for(int i = 0; i < len; i++){            int c = idx(s[i]);            if(!ch[u][c]){                memset(ch[sz], 0, sizeof(ch[sz]));                ch[u][c] = sz;                val[sz++] = 0;            }            u = ch[u][c];        }        val[u] = v;        val_id[v] = u;    }    void getFail()    {        queue<int> q;        last[0] = f[0] = 0;        for(int i = 0; i < sgm_sz; i++){            int u = ch[0][i];            if(u){                f[u] = last[u] = 0;                q.push(u);            }        }        while(!q.empty()){            int p = q.front();  q.pop();            for(int i = 0; i < sgm_sz; i++){                int u = ch[p][i];                if(!u){                    ch[p][i] = ch[f[p]][i];                    continue;                }                q.push(u);                int v = f[p];                while(v && !ch[v][i])   v = f[v];                f[u] = ch[v][i];                last[u] = val[f[u]] ? f[u] : last[f[u]];            }        }    }    /*void find(char *s)    {        int len = strlen(s), u = 0;        for(int i = 0; i < len; i++){            int c = idx(s[i]);            u = ch[u][c];            if(val[u])  deal(u);            else if(last[u])    deal(last[u]);        }    }    void deal(int u)    {        if(u){            //TODO            deal(last[u]);        }    }*/} ac;double a[maxn][maxn];int equ,var;//equ个方程,var个变量double x[maxn];//解集bool free_x[maxn];int n;int sgn(double x){    return (x>eps)-(x<-eps);}void print_a(){    for(int i = 0; i < equ; i++){        for(int j = 0; j <= var; j++){            printf("%.6f ", a[i][j]);        }lb;    }}void print_x(){    for(int i = 0; i < var; i++){        printf("x[%d]:%.6f\n",i,x[i]);    }}void gauss_build(int equ_par, int var_par){    memset(a, 0, sizeof(a));    memset(x, 0, sizeof(x));    equ = equ_par;    var = var_par;    auto val = ac.val;    auto ch = ac.ch;    int sz = ac.sz;    for(int i = 0; i < sz; i++){        a[i][i] += -1;        if(val[i]) continue;        for(int j = 0; j < sgm_sz; j++){            a[ch[i][j]][i] += 1.0/6;        }    }    a[0][var] += -1.0;}// 高斯消元法解方程组(Gauss-Jordan elimination).(0表示无解,1表示唯一解,大于1表示无穷解,并返回自由变元的个数)int gauss(){    //多少个方程,多少个变量    int i,j,k;    int max_r; // 当前这列绝对值最大的行.    int col; // 当前处理的列.    double temp;    int free_x_num;    int free_index;    // 转换为阶梯阵.    col = 0; // 当前处理的列.    memset(free_x,true,sizeof(free_x));    for(k = 0; k<equ && col<var; k++, col++){        max_r = k;        for(i = k+1; i < equ; i++){            if(sgn(fabs(a[i][col]) - fabs(a[max_r][col]))>0)                max_r = i;        }        if(max_r != k){ // 与第k行交换.            for(j = k; j < var+1; j++)                swap(a[k][j], a[max_r][j]);        }        if(sgn(a[k][col]) == 0){ // 说明该col列第k行以下全是0了,则处理当前行的下一列.            k--; continue;        }        for(i = k+1; i < equ; i++){ // 枚举要删去的行.            if (sgn(a[i][col]) != 0){                temp = a[i][col]/a[k][col];                for(j = col; j < var+1; j++){                    a[i][j] = a[i][j] - a[k][j]*temp;                }            }        }    }    for(i = k; i < equ; i++){        if(sgn(a[i][col]) != 0)            return 0;    }    if(k < var){        for(i = k-1; i >= 0; i--){            free_x_num = 0;            for(j = 0; j < var; j++){                if(sgn(a[i][j]) != 0 && free_x[j])                    free_x_num++,free_index=j;            }            if(free_x_num > 1) continue;            temp = a[i][var];            for(j = 0; j < var; j++){                if(sgn(a[i][j])!=0 && j!=free_index)                    temp -= a[i][j]*x[j];            }            x[free_index] = temp/a[i][free_index];            free_x[free_index] = 0;        }        return var-k;    }    for (i = var-1; i >= 0; i--){        temp = a[i][var];        for(j = i+1; j <var; j++){            if(sgn(a[i][j]) != 0)                temp -= a[i][j]*x[j];        }        x[i] = temp/a[i][i];    }    return 1;}int main(){    //frein;    //freout;    int n,t,l;    sc(t);    while(t--){        ac.init();        sc(n); sc(l);        char s[15];        for(int i = 1; i <= n; i++){            for(int j = 0; j < l; j++){                int k; sc(k);                s[j] = '0'+k;            }            s[l] = '\0';            ac.Insert(s, i);        }        ac.getFail();        gauss_build(ac.sz, ac.sz);        //print_a();        gauss();        //print_x();        for(int i = 1; i <= n; i++){            //printf("val_id[%d]:%d\n",i,ac.val_id[i]);            printf("%.6f%c", x[ac.val_id[i]], (i==n)?'\n':' ');        }    }return 0;}

用高斯消元求解状态矩阵的稳态解