zoukankan      html  css  js  c++  java
  • [JoyOI1519] 博彩游戏

    题目限制

    时间限制 内存限制 评测方式 题目来源
    1000ms 131072KiB 标准比较器 Local

    题目背景

    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个点~第10个点,每个点5分;
    第11个点~第15个点,每个点10分。

    对于样例的解释:
    随机序列一共有3^5=243个,其中包含"1"的个数为211个,则概率为211/243=0.86831Bob HAN

    样例数据

    输入样例 #1输出样例 #1
    5 1 3
    
    1
    
    
    0.86831

    和Bzoj1030基本一样。

    先对所有串建一个AC自动机。

    然后设$f[i][j]$为写的长度为i,正在自动机的第j个节点的方案数。

    设总方案数是$all$,那么答案就是(all - 不在末尾节点的方案数)/all。

    记得上传结束标记,有结束标记的点不往外转移。


    #include <bits/stdc++.h>
    using namespace std;
    #define reg register
    #define int long long
    #define N 400005
    int n, m, r;
    int nxt[N][10], fail[N], end[N];
    int tot;
    int f[105][N];
    int all = 1, ans;
    char s[30];
    
    inline void Ins()
    {
        int len = strlen(s);
        int now = 0;
        for (reg int i = 0 ; i < len ; i ++)
            now = nxt[now][s[i]-'0'] ? nxt[now][s[i]-'0'] : nxt[now][s[i]-'0'] = ++tot;
        end[now] = 1;
    }
    inline void AC_Match()
    {
        queue <int> q;
        for (reg int i = 1 ; i <= 9 ; i ++) 
            if (nxt[0][i]) q.push(nxt[0][i]);
        while(!q.empty())
        {
            int x = q.front();q.pop();
            for (reg int i = 1 ; i <= r ; i ++)
            {
                if (nxt[x][i]) fail[nxt[x][i]] = nxt[fail[x]][i], q.push(nxt[x][i]);
                else nxt[x][i] = nxt[fail[x]][i];
            }
            end[x] |= end[fail[x]];
        }
    }
    
    signed main()
    {
        scanf("%lld%lld%lld", &n, &m, &r);
        for (reg int i = 1 ; i <= m ; i ++)
        {
            scanf("%s", s);
            Ins();
        }
        AC_Match();
        f[0][0] = 1;
        for (reg int i = 0 ; i < n ; i ++)
            for (reg int x = 0 ; x <= tot ; x ++)
            {
                if (end[x] or !f[i][x]) continue;
                for (reg int j = 1 ; j <= r ; j ++)
                    f[i + 1][nxt[x][j]] += f[i][x];
            }
        for (reg int i = 1 ; i <= n ; i ++) all *= r;
        for (reg int i = 0 ; i <= tot ; i ++)
            if (!end[i]) ans += f[n][i];
        printf("%.5lf
    ", (double)(all - ans) / (double)all);
        return 0;
    }
  • 相关阅读:
    【理财启蒙】理财:需要树立正确的金钱观
    【系统设计】分布式唯一ID生成方案总结
    【Hash一致性算法】什么是Hash一致性算法
    【位图算法】什么是BitMap
    关于枚举类你可能不知道的事
    【数据结构】什么是AVL树
    mysql5.6 主从同步配置
    vmstat命令详解
    pstack跟踪进程栈
    iostat 磁盘io分析工具
  • 原文地址:https://www.cnblogs.com/BriMon/p/9690979.html
Copyright © 2011-2022 走看看