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

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


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

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;
#define pb push_back
#define mk make_pair
#define ll long long
#define ull unsigned long long
#define pii pair
#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<<"???"< 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 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; k0)
                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 

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

你可能感兴趣的:(打牌)