Bzoj1444 [Jsoi2009]有趣的游戏
2017-01-23 22:15
423 查看
Submit: 1075 Solved: 367
Description
Input
注意 是0<=P
Output
Sample Input
![](http://www.lydsy.com/JudgeOnline/images/1444_4.jpg)
Sample Output
![](http://www.lydsy.com/JudgeOnline/images/1444_5.jpg)
HINT
30%的数据保证, n ≤ 2. 50%的数据保证, n ≤ 5. 100%的数据保证, n , l, m≤ 10.
Source
概率
AC自动机+矩阵乘法
先建好AC自动机,得到不同字母间的转移关系。
对于每个结点,如果它是某个玩家的字符串末,则它转移到自己的概率为1,否则按照读入的概率转移到不同的字母去。
↑以此构建转移矩阵。
精度要求1-e2,那么尝试矩阵暴力自乘,使得概率趋于稳定。自乘30次精度不够,会WA,40次就过了。
/*by SilverN*/ #include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #include<cmath> #include<queue> using namespace std; const int mxn=50; int n,l,m; struct Aca{ int t[300][12]; int fail[300],end[300]; int pos[300]; int cnt,rt,id; void clear(){ cnt=0;memset(t,0,sizeof t);memset(fail,0,sizeof fail); rt=++cnt;id=0; return; } void insert(char s[]){ int len=strlen(s); int now=rt; for(int i=0;i<len;i++){ if(!t[now][s[i]-'A']) t[now][s[i]-'A']=++cnt; now=t[now][s[i]-'A']; } end[now]++; pos[++id]=now;//记录每个串末尾的结点编号 return; } void Build(){ queue<int>q; int i,j; for(i=0;i<m;i++){ if(t[rt][i]){ q.push(t[rt][i]); fail[t[rt][i]]=rt; } else t[rt][i]=rt; } while(!q.empty()){ int u=q.front();q.pop(); for(i=0;i<m;i++){ if(t[u][i]){ q.push(t[u][i]); fail[t[u][i]]=t[fail[u]][i]; } else t[u][i]=t[fail[u]][i]; } } } }; Aca a;//AC自动机 // struct Matrix{ double c[130][130]; int x; void clear(){memset(c,0,sizeof c);x=0;return;} friend Matrix operator * (Matrix a,Matrix b){ Matrix res; res.clear(); res.x=a.x; for(int i=1;i<=a.x;i++){ for(int j=1;j<=a.x;j++){ for(int k=1;k<=a.x;k++){ res.c[i][j]+=a.c[i][k]*b.c[k][j]; } } } return res; } }mp;//矩阵乘 char s[mxn]; double p[mxn]; int main(){ int i,j,P,Q; scanf("%d%d%d",&n,&l,&m); for(i=1;i<=m;i++){ scanf("%d%d",&P,&Q); p[i]=(double)P/Q; } a.clear(); for(i=1;i<=n;i++){ scanf("%s",s); a.insert(s); } a.Build(); for(i=1;i<=a.cnt;i++){//统计概率 if(a.end[i]) mp.c[i][i]=1; else for(j=0;j<m;j++){ mp.c[i][a.t[i][j]]+=p[j+1]; } } /* for(i=1;i<=a.cnt;i++){ for(j=1;j<=a.cnt;j++){ printf("%.3f ",mp.c[i][j]); } printf("\n"); } */ mp.x=a.cnt; for(i=1;i<=40;i++) mp=mp*mp; for(i=1;i<=n;i++) printf("%.2f\n",mp.c[1][a.pos[i]]); return 0; } /* 3 2 2 1 2 1 2 AB BA AA */
相关文章推荐
- 圆的运动-原生JS详解
- 解决eclipse中jsp没有代码提示问题
- [bzoj1820][JSOI2010][Express Service 快递服务] (动态规划)
- JavaScript动态向表格添加数据
- js阻止默认事件、拖拽等等
- 自动化运维Python系列之JavaScript作用域
- 掌握 Ajax,第 10 部分: 使用 JSON 进行数据传输
- js获取url传值
- <a href=javascript:alert()>aaa</a>
- js获取html代码中图片地址
- EJS指令--EJS 模板<%- 变量%> 与<%= 变量%>的区别
- JavaScript物体运动二
- JavaScript匿名函数和回调函数
- 通过一张简单的图,让你彻底地、永久地搞懂JS的==运算
- js字符串的分割
- 常用表单JS代码
- Javascript中的async await
- javascript基础:Math对象
- iscroll4划出边界stuck住的问题
- select2表单带出编辑,多选赋值问题