zoukankan      html  css  js  c++  java
  • 博彩游戏(tyvj 1519)

    背景

    Bob最近迷上了一个博彩游戏……

    描述

    这个游戏的规则是这样的:
    每花一块钱可以得到一个随机数R,花上N块钱就可以得到一个随机序列;
    有M个序列,如果某个序列是产生的随机序列的子串,那么就中奖了,否则不中。
    Bob会告诉你这M个序列,和身上有的钱的总数N,当然还有R的范围。
    请你告诉Bob中奖的概率有多少?

    输入格式

    第一行三个用空格隔开的数N、M和R的范围R。
    其中1<=R<=9,0<N<=60,0<M<=20000。
    下面M行每行一个字符串(长度小于等于20),字符串的每一位范围在1-r之间
    保证必要运算都在64位整型范围内。

    输出格式

    一行一个实数,表示中奖的概率(保留小数点后5位小数)。

    测试样例1

    输入

    5 1 3 
    1

    输出

    0.86831

    备注

    数据分布:
    第1个点~第10个点,每个点5分;
    第11个点~第15个点,每个点10分。

    对于样例的解释:
    随机序列一共有3^5=243个,其中包含"1"的个数为211个,则概率为211/243=0.86831Bob HAN
    /*
        AC自动机+DP 
        f[i][j]表示将字符串扩展到i,在自动机上匹配到j的概率。
        因为合法概率较难统计,所以最后答案为 1-不合法的概率。
        要滚动一下数组。
    */
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<queue>
    #define N 400010
    #define eps 0.000000001
    using namespace std;
    int a[N][10],danger[N],point[N],n,m,r,size=1;
    double f[2][N];char s[N];
    queue<int> q;
    void insert(){
        int len=strlen(s),now=1;
        for(int i=0;i<len;i++){
            int t=s[i]-'0';
            if(!a[now][t]) a[now][t]=++size;
            now=a[now][t];
        }
        danger[now]=1;
    }
    void build(){
        q.push(1);point[1]=0;
        while(!q.empty()){
            int now=q.front();q.pop();
            for(int i=1;i<=r;i++){
                if(!a[now][i]){
                    a[now][i]=a[point[now]][i];
                    continue;
                }
                int k=point[now];
                while(!a[k][i]) k=point[k];
                point[a[now][i]]=a[k][i];
                danger[a[now][i]]|=danger[point[a[now][i]]];
                q.push(a[now][i]);
            }
        }
    }
    void dp(){
        f[0][1]=1;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=size;j++){
                if(danger[j]||f[i+1&1][j]<eps) continue;
                for(int t=1;t<=r;t++){
                    int k=j;
                    while(!a[k][t]) k=point[k];
                    f[i&1][a[k][t]]+=f[i+1&1][j]/(double)r;
                }
            }
            for(int j=1;j<=size;j++)
                f[i+1&1][j]=0;
        }
    }
    int main(){
        scanf("%d%d%d",&n,&m,&r);
        for(int i=1;i<=r;i++) a[0][i]=1;
        for(int i=1;i<=m;i++){
            scanf("%s",s);
            insert();
        }
        build();dp();
        double ans=0;
        for(int i=1;i<=size;i++)
            if(!danger[i]) ans+=f[n&1][i];
        printf("%.5f",1.0-ans);
        return 0;
    }
  • 相关阅读:
    C语言第二次实验报告
    C语言第一次实验报告
    java远程开关机
    html5 总结
    css media 媒体查询
    移动端适配rem
    判断Android系统和iPhone系统 QQ游览器 微信
    原生javascript 选项卡封装
    浅谈坐标系以及之间的转换
    百度地图开发的学习(二)——地图定位
  • 原文地址:https://www.cnblogs.com/harden/p/6551079.html
Copyright © 2011-2022 走看看