UVALive - 3490 Generator (AC自动机+高斯消元dp)
初始有一个空串s,从前n个大写字母中不断随机取出一个字母添加到s的结尾,出现模式串t时停止,求停止时s的长度期望。
这道题解法不唯一,比较无脑的方法是对模式串t建一个单串AC自动机,设u为自动机上的一个结点,dp[u]为从该结点出发走到终结状态时的期望步数,则dp[u]=∑(1+dp[v])/n,v为u的后继状态。特别地,终结状态的dp值为0。
这样一来,就可以列出线性方程组进行高斯消元了。由于答案非常大,用double会损失精度,所以改成longlong。
由于有除法的存在,为了防止出现除不开的现象,我写了个大模数+逆元的版本,还需要用到按位乘。(闲的蛋疼系列)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll; const ll mod=(1ll<<)-;
int m,ka;
char s[];
ll Mul(ll x,ll p) {
if(p<)p+=mod;
ll ret=;
for(; p; x=(x+x)%mod,p>>=)if(p&)ret=(ret+x)%mod;
return ret;
}
ll Pow(ll x,ll p) {
ll ret=;
for(; p; x=Mul(x,x)%mod,p>>=)if(p&)ret=Mul(ret,x)%mod;
return ret;
}
ll inv(ll x) {return Pow(x,mod-);} struct Mat {
static const int N=;
int n;
ll a[N][N];
ll* operator[](int x) {return a[x];}
void gauss() {
for(int i=; i<n; ++i) {
int r=i;
if(!a[r][i]) {
for(int k=i+; k<n; ++k)if(a[k][i]) {r=k; break;}
}
if(r!=i)for(int j=i; j<=n; ++j)swap(a[i][j],a[r][j]);
for(int k=i+; k<n; ++k) {
ll tmp=Mul(a[k][i],inv(a[i][i]));
for(int j=i; j<=n; ++j)a[k][j]=(a[k][j]-Mul(a[i][j],tmp))%mod;
}
}
for(int i=n-; i>=; --i) {
for(int j=i+; j<n; ++j)a[i][n]=(a[i][n]-Mul(a[j][n],a[i][j]))%mod;
a[i][n]=Mul(a[i][n],inv(a[i][i]));
}
}
} G; struct AC {
static const int N=+,M=;
int go[N][M],pre[N],tot,end[N];
int idx(char ch) {return ch-'A';}
void init() {tot=; newnode();}
int newnode() {
int u=tot++;
memset(go[u],,sizeof go[u]);
end[u]=pre[u]=;
return u;
}
void ins(char* s) {
int u=,n=strlen(s);
for(int i=; i<n; u=go[u][idx(s[i])],++i)
if(!go[u][idx(s[i])])go[u][idx(s[i])]=newnode();
end[u]=;
}
void build() {
queue<int> q;
for(int i=; i<M; ++i)if(go[][i])q.push(go[][i]);
while(!q.empty()) {
int u=q.front();
q.pop();
for(int i=; i<M; ++i) {
if(go[u][i]) {
pre[go[u][i]]=go[pre[u]][i];
q.push(go[u][i]);
} else go[u][i]=go[pre[u]][i];
}
}
}
void gettransmat(Mat& G) {
G.n=tot;
int n=tot;
for(int i=; i<n; ++i)
for(int j=; j<=n; ++j)
G[i][j]=j==i?:;
for(int i=; i<tot; ++i)if(!end[i]) {
for(int j=; j<m; ++j)G[i][go[i][j]]=(G[i][go[i][j]]-inv(m))%mod;
G[i][n]=(G[i][n]+)%mod;
}
}
} ac; int main() {
int T;
scanf("%d",&T);
while(T--) {
if(ka)puts("");
printf("Case %d:\n",++ka);
ac.init();
scanf("%d%s",&m,s);
ac.ins(s);
ac.build();
ac.gettransmat(G);
G.gauss();
printf("%lld\n",(G[][G.n]+mod)%mod);
}
return ;
}
UVALive - 3490 Generator (AC自动机+高斯消元dp)的更多相关文章
- hdu 5955 Guessing the Dice Roll 【AC自动机+高斯消元】
hdu 5955 Guessing the Dice Roll [AC自动机+高斯消元] 题意:给出 n≤10 个长为 L≤10 的串,每次丢一个骰子,先出现的串赢,问获胜概率. 题解:裸的AC自动机 ...
- BZOJ 1444: [Jsoi2009]有趣的游戏 [AC自动机 高斯消元]
1444: [Jsoi2009]有趣的游戏 题意:每种字母出现概率\(p_i\),有一些长度len的字符串,求他们出现的概率 套路DP的话,\(f[i][j]\) i个字符走到节点j的概率,建出转移矩 ...
- UVALive 7455 Linear Ecosystem (高斯消元)
Linear Ecosystem 题目链接: http://acm.hust.edu.cn/vjudge/contest/127401#problem/B Description http://7xj ...
- bzoj 3143 [Hnoi2013]游走【高斯消元+dp】
参考:http://blog.csdn.net/vmurder/article/details/44542575 和2337有点像 设点u的经过期望(还是概率啊我也分不清,以下都分不清)为\( x[u ...
- bzoj 2337 [HNOI2011]XOR和路径【高斯消元+dp】
首先,我们发现,因为是无向图,所以相连的点之间是有"依赖性"的,所以不能直接用dp求解. 因为是xor,所以按位处理,于是列线性方程组,设$ x[i] $为点i到n异或和为1的期望 ...
- BZOJ.4820.[SDOI2017]硬币游戏(思路 高斯消元 哈希/AC自动机/KMP)
BZOJ 洛谷 建出AC自动机,每个点向两个儿子连边,可以得到一张有向图.参照 [SDOI2012]走迷宫 可以得到一个\(Tarjan\)+高斯消元的\(O((nm)^3)\)的做法.(理论有\(6 ...
- 【BZOJ1444】[JSOI2009]有趣的游戏(高斯消元,AC自动机)
[BZOJ1444][JSOI2009]有趣的游戏(高斯消元,AC自动机) 题面 BZOJ 题解 先把\(AC\)自动机构建出来,最好构成\(Trie\)图.然后这样子显然是在一个有向图中有一堆概率的 ...
- hdu5955 Guessing the Dice Roll【AC自动机】【高斯消元】【概率】
含高斯消元模板 2016沈阳区域赛http://acm.hdu.edu.cn/showproblem.php?pid=5955 Guessing the Dice Roll Time Limit: 2 ...
- 2016ACM/ICPC亚洲区沈阳站H - Guessing the Dice Roll HDU - 5955 ac自动机+概率dp+高斯消元
http://acm.hdu.edu.cn/showproblem.php?pid=5955 题意:给你长度为l的n组数,每个数1-6,每次扔色子,问你每个串第一次被匹配的概率是多少 题解:先建成ac ...
随机推荐
- 【转】JAVA学习笔记----PL/SQL最差实践
1. 超长的PL/SQL代码 影响:可维护性,性能 症状: 在复杂的企业应用中,存在动辄成百上千行的存储过程或上万行的包.为什么是最差: 太长的PL/SQL代码不利于阅读,第三方工 ...
- PictureBox 双缓冲防止闪屏
Bitmap bm = new Bitmap(this.pbTraffic.Image); BufferedGraphicsContext current = BufferedGraphicsMana ...
- android studio的安装和卸载
安装: (待补充) 卸载: (如何彻底卸载才能达到第二次安装不受第一次安装失败的影响呢?) 1.找到安装目录,运行卸载文件.(不用清注册表,这是和卸载mysql的不同,只要把相关的文件夹,文件清楚即可 ...
- POJ 3468 A Simple Problem with Integers 【线段树】
题目链接 http://poj.org/problem?id=3468 思路 线段树 区间更新 模板题 在赋初始值的时候,按点更新区间就可以 AC代码 #include <cstdio> ...
- iOS 快速遍历 效率分析 for loop for in enumerateBlock 适用条件
test1 简单遍历 结论: 当数组数据量很小 时候 for loop 和 for in 效率不相上下,随着数据量增长for in 快速枚举的优势 明显 如果需要知道 索引可用 enumrateBlo ...
- 转:CWebBrowser2去除边框、滚动条、右键菜单
http://blog.csdn.net/tangyin025/article/details/8675513 添加CWebBrowser2类 右键项目-〉Add-〉Class...-〉MFC-〉MF ...
- OpenGL学习进程(7)第五课:点、边和图形(二)边
本节是OpenGL学习的第五个课时,下面介绍OpenGL边的相关知识: (1)边的概念: 数学上的直线没有宽度,但OpenGL的直线则是有宽度的.同时,OpenGL的直线必须是有限长度,而不是像数学概 ...
- Vuex mapGetters,mapActions
一.基本用法 1. 初始化并创建一个项目 ? 1 2 3 vue init webpack-simple vuex-demo cd vuex-demo npm install 2. 安装 vuex ? ...
- 斯坦福机器学习视频笔记 Week7 支持向量机 Support Vector Machines
SVM被许多人认为是最强大的“黑箱”学习算法,并通过提出一个巧妙选择的优化目标,今天最广泛使用的学习算法之一. Optimization Objective 根据Logistic Regression ...
- Centos 一次卸载多个RPM包
rpm 不支持通配符,可以使用 xargs来接收多个变量 示例,一次性卸载所有 erlang先关的rpm包: rpm -qa | grep erlang | xargs rpm -e --nodeps