P1519 博彩游戏

时间: 1000ms / 空间: 131072KiB / Java类名: Main

背景

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自动机后,在AC自动机上做DP,这里要用到滚动数组。
用f[i][j]来表示长度为i,转移到j号节点时没有构成任意一个单词时的情况。
总情况是r^n减去Σf[n][i]即可。。。
 1 #include<set>
 2  #include<cstdio>
 3  #include<queue>
 4  #include<cstring>
 5  #include<iostream>
 6  using namespace std;
 7  typedef long long LL;
 8    const int N=20000+5,L=20+5;
 9    const int node = N*L;
10    const int sigma = 10;
11    
12    char s[L]; int n,m,r; LL d[2][node];
13    
14    struct ACauto{
15        int ch[node][sigma],f[node],val[node],sz;
16        void clear() {
17            sz=1; memset(ch[0],0,sizeof(ch[0]));
18        }
19        void insert(char *s) {
20            int n=strlen(s),u=0;
21            for(int i=0;i<n;i++) {
22                int c=s[i]-'1';
23                if(!ch[u][c]) {
24                    memset(ch[sz],0,sizeof(ch[sz]));
25                    val[sz]=0; ch[u][c]=sz++;
26                }
27                u=ch[u][c];
28            }
29            val[u]=1;
30        }
31        void get_Fail() {
32            queue<int> q;
33            f[0]=0;
34            for(int c=0;c<r;c++) 
35                if(ch[0][c]) f[ch[0][c]]=0,q.push(ch[0][c]);
36            while(!q.empty()) {
37                int qr=q.front(); q.pop();
38                for(int c=0;c<r;c++) {
39                    int u=ch[qr][c]; if(!u) continue;
40                    q.push(u);  int v=f[qr];
41                    while(v&&!ch[v][c]) v=f[v];
42                    if(val[ch[v][c]]) val[u]=1;
43                    f[u]=ch[v][c];
44                }
45            }
46         }
47    }ac;
48    int que[2][N],cnt[2];
49    int main() {
50        //freopen("in.in","r",stdin);
51        //freopen("out.out","w",stdout);
52        scanf("%d%d%d",&m,&n,&r);
53        ac.clear();
54        for(int i=0;i<n;i++) {
55            scanf("%s",s); ac.insert(s);
56        }
57        ac.get_Fail();
58        d[0][0]=1;
59        int x=0;
60        for(int i=1;i<=m;i++) {
61            x^=1;
62            memset(d[x],0,sizeof(d[x]));
63            for(int j=0;j<ac.sz;j++) if(!ac.val[j]&&d[x^1][j]) {
64                for(int c=0;c<r;c++) {
65                    int k=j; while(!ac.ch[k][c]&&k) k=ac.f[k];
66                    d[x][ac.ch[k][c]]=d[x^1][j]+d[x][ac.ch[k][c]];
67                }
68            }
69        }
70        LL ans1=0,ans2=1;
71        for(int i=1;i<=m;i++) ans2*=(LL)r;
72        for(int i=0;i<ac.sz;i++)
73            if(!ac.val[i]) ans1+=d[x][i];
74        double f=((double)ans2-(double)ans1)/(double)ans2;
75        printf("%.5f\n",f);
76        return 0;
77    }
View Code

 

posted @ 2016-06-16 10:18  HTWX  阅读(137)  评论(0编辑  收藏  举报