zoukankan      html  css  js  c++  java
  • BZOJ4820 Sdoi2017 硬币游戏 【概率期望】【高斯消元】【KMP】*

    BZOJ4820 Sdoi2017 硬币游戏


    Description

    周末同学们非常无聊,有人提议,咱们扔硬币玩吧,谁扔的硬币正面次数多谁胜利。大家纷纷觉得这个游戏非常符合同学们的特色,但只是扔硬币实在是太单调了。同学们觉得要加强趣味性,所以要找一个同学扔很多很多次硬币,其他同学记录下正反面情况。用H表示正面朝上,用T表示反面朝上,扔很多次硬币后,会得到一个硬币序列。比如HTT表示第一次正面朝上,后两次反面朝上。但扔到什么时候停止呢?大家提议,选出n个同学,每个同学猜一个长度为m的序列,当某一个同学猜的序列在硬币序列中出现时,就不再扔硬币了,并且这个同学胜利,为了保证只有一个同学胜利,同学们猜的n个序列两两不同。很快,n个同学猜好序列,然后进入了紧张而又刺激的扔硬币环节。你想知道,如果硬币正反面朝上的概率相同,每个同学胜利的概率是多少。

    Input

    第一行两个整数n,m。
    接下里n行,每行一个长度为m的字符串,表示第i个同学猜的序列。
    1<=n,m<=300

    Output

    输出n行,第i行表示第i个同学胜利的概率。
    输出与标准输出的绝对误差不超过10^-6即视为正确。

    Sample Input

    3 3
    THT
    TTH
    HTT

    Sample Output

    0.3333333333
    0.2500000000
    0.4166666667



    #include<bits/stdc++.h>
    using namespace std;
    #define N 310
    #define eps 1e-3
    #define For(a,b,c) for(int a=b;a<=c;a++)
    int n,m;
    double g[N][N];
    void guass(){
        For(i,1,n){
            int p=i;
            For(j,i,n)if(abs(g[j][i])>abs(g[p][i]))p=j;
            For(j,1,n+1)swap(g[p][j],g[i][j]);
            double d=g[i][i];
            For(j,1,n+1)g[i][j]/=d;
            For(j,1,n){
                if(i==j)continue;
                double w=g[j][i];
                For(k,1,n+1)g[j][k]-=g[i][k]*w;
            }
        }
        For(i,1,n-1)printf("%.10lf
    ",g[i][n+1]);
    }
    int fail[N][N];
    int s[N][N];
    double p[N];
    void init(int id){
        For(i,2,m){
            int j=fail[id][i-1];
            while(j&&s[id][i]!=s[id][j+1])j=fail[id][j];
            if(s[id][i]==s[id][j+1])fail[id][i]=j+1;
            else fail[id][i]=0;
        }
    }
    double kmp(int ida,int idb){
        int j=0;
        For(i,1,m){
            while(j&&s[idb][i]!=s[ida][j+1])j=fail[ida][j];
            if(s[idb][i]==s[ida][j+1])++j;
        }
        double res=0;
        while(j){
            res+=p[m-j];
            j=fail[ida][j];
        }
        return res;
    }
    int main(){
        scanf("%d%d",&n,&m);
        p[0]=1;For(i,1,m)p[i]=p[i-1]*0.5;
        For(i,1,n){
            static char c[N];
            scanf("%s",c+1);
            For(j,1,m)
                if(c[j]=='H')s[i][j]=1;
                else s[i][j]=0;
            init(i);
        }
        For(i,1,n)For(j,1,n)g[i][j]=kmp(i,j);
        For(i,1,n)g[i][n+1]=-p[m];
        For(i,1,n)g[n+1][i]=1;
        g[n+1][n+2]=1;
        n++;
        guass();
        return 0;
    }
  • 相关阅读:
    javascript数组查重方法总结
    html5的web存储
    掌握javascript中的最基础数据结构-----数组
    ES解决geoip的location不为geo_point格式
    elk默认分片只有1000导致索引没有创建
    Polysh批量管理服务器
    Git永久删除文件和历史记录
    windows下设置JupyterNotebook默认目录
    windwos安装RabbitMQ
    win7计划任务报该任务映像己损坏或己篡改
  • 原文地址:https://www.cnblogs.com/dream-maker-yk/p/9676290.html
Copyright © 2011-2022 走看看