http://www.elijahqi.win/archives/3222
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
第一行包含三個正整數N、len、alphabet。
接下來N行,每行包含一個串Ti,表示禁忌串。
Output
一個非負實數,表示所受到禁忌傷害的期望值。
Sample Input
2 4 2
aa
abb
Sample Output
0.75
【樣例1解釋】
一共有2^4 = 16種不同的魔法。
需要注意的是“aabb”的禁忌傷害是1而不是2。
HINT
100%的資料中N ≤ 5,len ≤109,1 ≤ alphabet ≤ 26。
在所有資料中,有不少于40%的資料中:N = 1。
資料保證每個串Ti的長度不超過15,并且不是空串。
資料保證每個Ti均僅含有前alphabet個小寫字母。
資料保證集合T中沒有相同的元素,即對任意不同的i和j,有Ti≠Tj。
【評分方法】
對于每一組資料,如果沒有得到正确的輸出(TLE、MLE、RTE、輸出格式錯誤等)得0分。
否則:設你的輸出是YourAns,标準輸出是StdAns:
記MaxEPS = max(1.0 , StdAns)×10-6
如果|YourAns – StdAns| ≤ MaxEPS則得10分,否則得0分。
即:你的答案需要保證相對誤差或絕對誤差不超過10-6。
Source
mdzz 矩陣乘法轉移忘記累加答案
考慮這個s是固定的怎麼做 相當于有很多線段 即給定的那n個字元串 求用最多的線段覆寫s能用多少個
那麼這道題把他給定的這些串建AC自動機
然後每次在AC自動機上貪心比對 如果比對到了一個就給我答案++ 然後使得我目前重新從頭開始比對
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ld long double
using namespace std;
int cnt=1,trans[100][26],fail[100],n,len,a;bool end[100];
inline void insert1(char *s){int p=1;
for (int i=1,nxt;s[i];++i){
if (!trans[p][s[i]-'a']) trans[p][s[i]-'a']=nxt=++cnt;
else nxt=trans[p][s[i]-'a'];p=nxt;
}end[p]=1;
}
struct matrix{ld f[100][100];}tr,ans;
inline matrix multiply(const matrix &a,const matrix &b){
matrix c;memset(c.f,0,sizeof(c.f));
for (int i=1;i<=cnt;++i)
for (int k=1;k<=cnt;++k)
for (int j=1;j<=cnt;++j)
c.f[i][j]+=a.f[i][k]*b.f[k][j];
return c;
}
inline void buildAC(){
queue<int>q;q.push(1);for (int i=0;i<a;++i) trans[0][i]=1;
while(!q.empty()){
int x=q.front();q.pop();
for (int i=0;i<a;++i){
int &y=trans[x][i];
if (!y) {y=trans[fail[x]][i];continue;}
fail[y]=trans[fail[x]][i];q.push(y);end[y]|=end[fail[y]];
}
}
}
char s[100];
int main(){
freopen("bzoj2553.in","r",stdin);
scanf("%d%d%d",&n,&len,&a);ld v=(ld)1/a;
for (int i=1;i<=n;++i) scanf("%s",s+1),insert1(s);
buildAC();ans.f[1][1]=1;++cnt;
for (int i=1;i<cnt;++i){
for (int j=0;j<a;++j){
int y=trans[i][j];
if (end[y]) tr.f[i][1]+=v,tr.f[i][cnt]+=v;else tr.f[i][y]+=v;
}
}tr.f[cnt][cnt]=1;
for (int t=len;t;t>>=1,tr=multiply(tr,tr)) if (t&1) ans=multiply(ans,tr);
printf("%.10f\n",(double)ans.f[1][cnt]);
return 0;
}