2553: [BeiJing2011]禁忌

Time Limit: 20 Sec  Memory Limit: 128 MBSec  Special Judge
Submit: 203  Solved: 75
[Submit][Status]

Description

Magic Land上的人们总是提起那个传说:他们的祖先John在那个东方岛屿帮助Koishi与其姐姐Satori最终战平。而后,Koishi恢复了读心的能力……

如今,在John已经成为传说的时代,再次造访那座岛屿的人们却发现Koishi遇到了新麻烦。

这次她遇到了Flandre Scarlet——她拥有可以使用禁忌魔法而不会受到伤害的能力。

为了说明什么是禁忌魔法及其伤害,引入以下概念:

1.字母集A上的每个非空字符串对应了一个魔法。

其中A是包含了前alphabet个小写字母的集合。

2.有一个集合T,包含了N个字母集A上的字符串

T中的每一串称为一个禁忌串(Taboo string

3.一个魔法,或等价地,其对应的串s因为包含禁忌而对使用者造成的伤害按以下方式确定:

s分割成若干段,考虑其中是禁忌串的段的数目,不同的分割可能会有不同的数目,其最大值就是这个伤害。

由于拥有了读心的能力,Koishi总是随机地使用Flandre Scarlet的魔法,可以确定的是,她的魔法正好对应字母集A上所有长度为len的串

但是,Flandre Scarlet所使用的一些魔法是带有禁忌的,由于其自身特性,她可以使用禁忌魔法而不受到伤害,而Koishi就不同了。可怜的Koishi每一次使用对方的魔法都面临着受到禁忌伤害的威胁。

你现在需要计算的是如果Koishi使用对方的每一个魔法的概率是均等的,那么每一次随机使用魔法所受到的禁忌伤害的期望值是多少。

Input

第一行包含三个正整数Nlenalphabet

接下来N行,每行包含一个串Ti,表示禁忌串。

Output

一个非负实数,表示所受到禁忌伤害的期望值。

Sample Input

2 4 2

aa

abb

Sample Output

0.75

【样例1解释】
一共有2^4 = 16种不同的魔法。

需要注意的是“aabb”的禁忌伤害是1而不是2。

HINT

100%的数据中N ≤ 5len ≤1091 ≤ alphabet ≤ 26

在所有数据中,有不少于40%的数据中:N = 1

数据保证每个串Ti的长度不超过15,并且不是空串。

数据保证每个Ti均仅含有前alphabet个小写字母。

数据保证集合T中没有相同的元素,即对任意不同的ij,有TiTj

【评分方法】

对于每一组数据,如果没有得到正确的输出(TLE、MLE、RTE、输出格式错误等)得0分。

否则:设你的输出是YourAns,标准输出是StdAns

MaxEPS = max(1.0 , StdAns)×10-6

如果|YourAns – StdAns| ≤ MaxEPS则得10分,否则得0分。

即:你的答案需要保证相对误差或绝对误差不超过10-6

题解:

出题人果然丧心病狂卡精度。。。

这题写题解的人好像不多,也许是我太傻叉了,时光机的代码画面太美我都不敢看了。。。

首先我们先搞清一个问题,如果给定了一个字符串,那么它的伤害指数是多少。

转化一下就变成 在一个数轴上给定若干条线段,请选出最多的线段并且使得这些线段两两交集为空。

然后这就是一个贪心水题,见http://www.cnblogs.com/zyfzyf/p/4006703.html

我们只要按右端点排序,能取就取。

那假如我们已经构建了一个AC自动机,我们只要走到一个危险节点,就ans++,并且退回到根节点重新开始走。

可以看出,这样正好相当于在模拟上面的贪心过程。

然后我们看看len增加1,我们能干什么

建图如下:

void build()
{
vis[]=;
q.push();long double tmp=1.0/k;
while(!q.empty())
{
int x=q.front();q.pop();
for0(i,k-)
{
if(!vis[t[x][i]])vis[t[x][i]]=,q.push(t[x][i]);
if(v[t[x][i]])
{
a.d[x][n]+=tmp;
a.d[x][]+=tmp;
}else a.d[x][t[x][i]]+=tmp;
}
}
}

意思就是我们把所有这样的关系找出来,如果len结束时,我们在x。

那如果t[x][i]是根节点,那我们就有1.0/alp的期望使ans+1,并返回根节点,否则我们有1.0/alp的期望走到t[x][i]。

最后我们求长度为给定是从1走到ans(设置为节点n)的期望次数即可。

然后这个矩阵构建出来我们发现 i到j的期望就等于sigma(i到k的期望*k到j的期望)。

这正好是矩阵乘法!

然后我们就可用快速幂加速了。

注意设置a[n][n]=1

代码:

 #include<cstdio>

 #include<cstdlib>

 #include<cmath>

 #include<cstring>

 #include<algorithm>

 #include<iostream>

 #include<vector>

 #include<map>

 #include<set>

 #include<queue>

 #include<string>

 #define inf 1000000000

 #define maxn 200+5

 #define eps 1e-10

 #define ll long long

 #define pa pair<int,int>

 #define for0(i,n) for(int i=0;i<=(n);i++)

 #define for1(i,n) for(int i=1;i<=(n);i++)

 #define for2(i,x,y) for(int i=(x);i<=(y);i++)

 #define for3(i,x,y) for(int i=(x);i>=(y);i--)

 #define mod 1000000007

 using namespace std;

 inline int read()

 {

     int x=,f=;char ch=getchar();

     while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}

     while(ch>=''&&ch<=''){x=*x+ch-'';ch=getchar();}

     return x*f;

 }
int n,m,k,cnt,t[maxn][],go[maxn];
bool v[maxn],vis[maxn];
queue<int>q;
char s[maxn];
struct matrix
{
long double d[maxn][maxn];
matrix(){memset(d,,sizeof(d));}
}a,b,c;
inline void add()
{
scanf("%s",s+);int len=strlen(s+),now=;
for1(i,len)
{
int x=s[i]-'a';
if(!t[now][x])t[now][x]=++cnt;
now=t[now][x];
}
v[now]=;
}
void bfs()
{
q.push();
while(!q.empty())
{
int x=q.front(),y,j;q.pop();
v[x]|=v[go[x]];
for0(i,k-)
{
j=go[x];
while(j&&!t[j][i])j=go[j];
if(t[x][i])
{
go[y=t[x][i]]=j?t[j][i]:;
q.push(y);
}else t[x][i]=j?t[j][i]:;
}
}
}
void build()
{
vis[]=;
q.push();long double tmp=1.0/k;
while(!q.empty())
{
int x=q.front();q.pop();
for0(i,k-)
{
if(!vis[t[x][i]])vis[t[x][i]]=,q.push(t[x][i]);
if(v[t[x][i]])
{
a.d[x][n]+=tmp;
a.d[x][]+=tmp;
}else a.d[x][t[x][i]]+=tmp;
}
}
}
inline matrix operator *(matrix &x,matrix &y)
{
matrix z;
for1(i,n)
for1(j,n)
for1(l,n)
z.d[i][j]+=x.d[i][l]*y.d[l][j];
return z;
}
void ksm(int cs)
{
for(;cs;cs>>=,a=a*a)
if(cs&)b=b*a;
}
void printb()
{
for1(i,n)for1(j,n)cout<<i<<' '<<j<<' '<<b.d[i][j]<<endl;
}
void printa()
{
for1(i,n)for1(j,n)cout<<i<<' '<<j<<' '<<a.d[i][j]<<endl;
} int main() { freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); n=read();m=read();k=read();cnt=;
for1(i,n)add();
bfs();
n=cnt+;
build();
for1(i,n)b.d[i][i]=;
a.d[n][n]=;
ksm(m);
printf("%.7f\n",(double)b.d[][n]); return ; }

真是一道综合性的难题+好题!

UPD:以上纯属口胡。。。

一个边权为1的邻接矩阵自乘n次,则a[s][t]代表从s恰好经过n条边到t的路径条数。

根据这一点我们可以推广

令a[i][j]表示一步从i到j的期望,那么a自乘n次就a[s][t]就代表从s恰好经过n条边到达t的期望。

然后我们新建了一给点n=cnt+1

然后我们要求sigma(从1到n恰好经过j条边的期望)j<=len

所以我们要设值a[n][n]=1,因为下一次计算的时候b[1][n]=。。。+b[1][n]*a[n][n]+。。。就可以把上一次的答案累计。

就算是我懂了QAQ

BZOJ2553: [BeiJing2011]禁忌的更多相关文章

  1. [BZOJ2553][BeiJing2011]禁忌 dp+AC自动机+矩阵快速幂

    2553: [BeiJing2011]禁忌 Time Limit: 20 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 1206  Solved ...

  2. BZOJ2553 [BeiJing2011]禁忌 AC自动机 矩阵

    原文链接http://www.cnblogs.com/zhouzhendong/p/8196279.html 题目传送门 - BZOJ2553 题意概括 引用一下lych大佬的: 在字母只有前alph ...

  3. BZOJ2553[BeiJing2011]禁忌——AC自动机+概率DP+矩阵乘法

    题目描述 Magic Land上的人们总是提起那个传说:他们的祖先John在那个东方岛屿帮助Koishi与其姐姐Satori最终战平.而后,Koishi恢复了读心的能力…… 如今,在John已经成为传 ...

  4. BZOJ2553 Beijing2011禁忌(AC自动机+动态规划+矩阵快速幂+概率期望)

    考虑对一个串如何分割能取得最大值.那么这是一个经典的线段覆盖问题,显然每次取右端点尽量靠前的串.于是可以把串放在AC自动机上跑,找到一个合法串后就记录并跳到根. 然后考虑dp.设f[i][j]表示前i ...

  5. BZOJ2553 [BeiJing2011]禁忌 【AC自动机 + dp + 矩乘优化】

    题目链接 BZOJ2553 题解 话说在前,此题卡精度,最好开long double 先建\(AC\)自动机 求期望,逆着求,设\(f[i][j]\)为长度为\(i\)的串,当前匹配AC自动机\(j\ ...

  6. 【BZOJ】2553: [BeiJing2011]禁忌 AC自动机+期望+矩阵快速幂

    [题意]给定n个禁忌字符串和字符集大小alphabet,保证所有字符在集合内.一个字符串的禁忌伤害定义为分割能匹配到最多的禁忌字符串数量(一个可以匹配多次),求由字符集构成的长度为Len的字符串的期望 ...

  7. 【BZOJ2553】[BeiJing2011]禁忌 AC自动机+期望DP+矩阵乘法

    [BZOJ2553][BeiJing2011]禁忌 Description Magic Land上的人们总是提起那个传说:他们的祖先John在那个东方岛屿帮助Koishi与其姐姐Satori最终战平. ...

  8. 【bzoj2553】[BeiJing2011]禁忌

    2553: [BeiJing2011]禁忌 Time Limit: 20 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 595  Solved: ...

  9. bzoj 2553 [BeiJing2011]禁忌——AC自动机+概率DP+矩阵

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2553 看了题解才会…… 首先,给定一个串,最好的划分方式是按禁忌串出现的右端点排序,遇到能填 ...

随机推荐

  1. 05_XML的解析_01_dom4j 解析

    [简述] Xml文件出了给开发者看,更多情况使用程序读取xml文件里的内容,这叫做xml解析. 根据解析方式分为:DOM解析 和 SAX解析 [解析工具] (一). 使用DOM解析原理的工具: 1.J ...

  2. 只有PD号的调起

    cicsterm-> CECI -> LI-> P -> TestQuery

  3. 关于js与php互相传值的介绍【转载+自身总结】

    JS是前台的语言,PHP是后台的语言,初学时会经常出现前后台分不清的情况(我当初就是这样的,现在有时也在犯),我当初的想法是就把前后台当成两个岛,他们是无法跨越的,HTML就像一座桥,当你想要把一座岛 ...

  4. 【转】Ubuntu编译安装mysql源码

    主要参考了下面两篇文章 http://forum.ubuntu.org.cn/viewtopic.php?t=330121 http://www.linuxidc.com/Linux/2011-09/ ...

  5. 51nod1174区间中最大的数

    1174 区间中最大的数基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 收藏 关注给出一个有N个数的序列,编号0 - N - 1.进行Q次查询,查询编号i至j的所有数中, ...

  6. dataTable 禁止显示信息

    $("#id").DataTable({ "info": false, // 禁止显示信息 });

  7. ZeroMQ/jzmq安装使用

    环境: No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 12.04.2 LTS Release: 12 ...

  8. Python 3.5 for windows 10 通过pip安装mysqlclient模块 error:C1083

    $pip install mysqlclient 运行结果如下: 可能是由于不兼容导致的(中间试过各种方法,比如本地安装mysql等等),最后找来mysqlclient-1.3.7-cp35-cp35 ...

  9. js常见事件

    1.onblur:(使用在表单元素中,当元素失去焦点的时候执行) 2.onchange:(使用在表单元素中,当某些东西改变是执行) 3.onclick:(鼠标点击一个元素时执行) 4.ondblcli ...

  10. 从ng-repeat到NgFor

    看这篇文章基本明白怎么渲染模板,但是我的工程会报错说#号非法,这篇的写法也不好用. angular2.0.0的语法集: Angular for TypeScript 语法快速指南 (基于2.0.0版本 ...