BZOJ1444: [Jsoi2009]有趣的游戏 矩阵求逆+AC自动机
来源:互联网 发布:美国原油进口数据 编辑:程序博客网 时间:2024/05/21 11:29
题意:N个人,每个人有一个长度为L的字符串,字符都在前M个大写字母中,现开始连续地随机产生字符,每次产生某个字符的概率是固定的,当一个人的字符串被产生出来他就赢了,求每个人赢的概率。
N,M,L<=10
百度了一下没查着和我一样用矩阵求逆做的。。。好像精度要求不高,邻接矩阵自乘几次就能过?
算了。。。首先赢不了的人可以特判掉,所有人都赢不了就直接退出(我觉得这样应该可以防止矩阵不可逆),建一下AC自动机,就可以把邻接矩阵搞出来,注意单词结点没有任何出边(这题由于所有人单词长度都一样,不存在一个单词结点可能被另一个结点的fail指针指向的情况)
我们要求的每个人获胜的概率等于转移一次获胜的概率+转移两次获胜的概率+……+转移无穷次获胜的概率。设T为初始的邻接矩阵,X为每次转移后的矩阵之和,即:
X=T^1+T^2+T^3+⋯+T^∞
TX=T^2+T^3+⋯+T^∞
(1-T)X=T
所以用T乘以(1-T)的逆矩阵即可(1为单位矩阵),最后X[0][N]就是从0号节点(根)转移到N号结点的概率。
矩阵求逆的过程就是和高斯消元解线性方程组一样,不过未知数不是N个数字,而是N个行向量,然后把原矩阵放在左面,单位矩阵放在右面,左边原矩阵消成单位矩阵之后右边的单位矩阵就会变成原矩阵的逆矩阵。
话说我不会严格证明这题里的矩阵一定可逆。。。如果有路过的神犇明白的话欢迎赐教。
#include<cstdio>#include<queue>#include<cmath>#include<algorithm>#define gm 101using namespace std;int maxn;int n,m,l;inline void __swap(double *a,double *b){ int tms=maxn; while(tms--) iter_swap(a++,b++);}struct martix{ double m[gm][gm]; martix():m(){} martix(int):m() { for(int i=0;i<=maxn;++i) m[i][i]=1; } inline double* operator [] (size_t x) {return m[x];} inline const double* operator [] (size_t x) const {return m[x];} inline martix operator - (const martix& b) const { martix res; for(int i=0;i<=maxn;++i) for(int j=0;j<=maxn;++j) res[i][j]=m[i][j]-b[i][j]; return res; } inline martix operator * (const martix &b) const { martix res; for(int i=0;i<=maxn;++i) for(int j=0;j<=maxn;++j) for(int k=0;k<=maxn;++k) res[i][j]+=m[i][k]*b[k][j]; return res; } inline void inv() { martix res(1); for(int i=0;i<=maxn;++i) { for(int j=i;j<=maxn;++j) if(fabs(m[j][i])>1e-6) { if(i!=j) __swap(m[i],m[j]),__swap(res[i],res[j]); break; } for(int j=i+1;j<=maxn;++j) { double temp=m[j][i]/m[i][i]; for(int k=i;k<=maxn;++k) m[j][k]-=m[i][k]*temp; for(int k=0;k<=maxn;++k) res[j][k]-=res[i][k]*temp; } } for(int i=maxn;i>=0;--i) { for(int j=0;j<=maxn;++j) res[i][j]/=m[i][i]; for(int j=i-1;j>=0;--j) { for(int k=0;k<=maxn;++k) res[j][k]-=res[i][k]*m[j][i]; } } *this=res; } inline martix operator / (martix &b) const { b.inv(); return operator*(b); }}t,u;double ps[26];struct node{ node *s[26],*fail; bool da; node():s(),fail(),da(){} inline void* operator new(size_t);}pool[gm];inline void* node::operator new(size_t){ static int t=-1; return pool+ ++t;}struct acam{ node *rt; acam():rt(new node){rt->fail=rt;} inline void insert(const char *s,int& pos) { node *now=rt; while(*s) { node*& x=now->s[*s-'A']; if(!x) x=new node; now=x; ++s; } now->da=1; pos=now-pool; } inline void aho_corasick() { queue<node*> q; maxn=0; for(int i=0;i<m;++i) { node*& x=rt->s[i]; if(!x) x=rt; else x->fail=rt,q.push(x); } while(!q.empty()) { ++maxn; node *now=q.front();q.pop(); for(int i=0;i<m;++i) { node*& x=now->s[i]; if(!x) x=now->fail->s[i]; else x->fail=now->fail->s[i],q.push(x); } } }}ac;int p,q,pos[11];bool lose[11];char s[11];int main(){ scanf("%d%d%d",&n,&l,&m); for(int i=0;i<m;++i) { scanf("%d%d",&p,&q); ps[i]=double(p)/q; } for(int i=0;i<n;++i) { scanf("%s",s); for(int j=0;s[j];++j) if(fabs(ps[s[j]-'A'])<1e-6) { lose[i]=1; break; } if(lose[i]) continue; ac.insert(s,pos[i]); } bool skip=1; for(int i=0;i<n;++i) { if(!lose[i]) { skip=0; break; } } if(skip) goto calc; ac.aho_corasick(); for(int i=0;i<=maxn;++i) if(!pool[i].da) { for(int j=0;j<m;++j) t[i][pool[i].s[j]-pool]+=ps[j]; } u=martix(1)-t; t=t/u; calc: for(int i=0;i<n;++i) { if(lose[i]) puts("0.00"); else printf("%.2lf\n",t[0][pos[i]]); } return 0;}
0 0
- BZOJ1444: [Jsoi2009]有趣的游戏 矩阵求逆+AC自动机
- 【bzoj1444】【jsoi2009】【有趣的游戏】【AC自动机+矩阵乘法】
- bzoj1444: [Jsoi2009]有趣的游戏
- BZOJ 1444 JSOI2009 有趣的游戏 AC自动机+矩阵乘法
- 【 bzoj 1444 】 [Jsoi2009]有趣的游戏 - AC自动机+矩阵乘法
- BZOJ1444 有趣的游戏【AC自动机、概率DP】
- [AC自动机 概率DP 矩阵乘法||高斯消元] BZOJ 1444 [Jsoi2009]有趣的游戏
- BZOJ 1444: [Jsoi2009]有趣的游戏 AC自动机加矩阵快速幂
- HYSBZ 1444 有趣的游戏 AC自动机+概率DP+高斯消元
- BZOJ 1444 [Jsoi2009] 有趣的游戏
- bzoj 1444 [Jsoi2009]有趣的游戏
- Matrix Matcher uva+AC自动机+求子矩阵出现的次数
- 两个AC自动机+矩阵的题
- AC自动机加矩阵
- AC自动机+矩阵+二分
- POJ2778 AC自动机 + 矩阵
- poj2778 ac自动机+矩阵
- ac自动机+矩阵
- JAVA 枚举单例模式及源码分析
- [Leetcode] Best Time to Buy and Sell Stock II
- Java基础——Collection与Collections的区别
- 机器人的运动范围
- Java链表的基本操作
- BZOJ1444: [Jsoi2009]有趣的游戏 矩阵求逆+AC自动机
- input子系统五 多点上报协议
- TableView异常failed to obtain a cell from its dataSource
- 类似淘宝商品展示,上面图片下面名字和标题的css样式设置
- 实现数据库的批处理两种方式,以及比较其优缺点
- Android开发中 MVP模式
- iOS关于导航控制器
- 面试算法学习-4-字符串全排列
- js 判断数据类型