bzoj 1444 [Jsoi2009]有趣的游戏

1444: [Jsoi2009]有趣的游戏

Time Limit: 10 Sec   Memory Limit: 64 MB
Submit: 1306   Solved: 466
[ Submit][ Status][ Discuss]

Description

Input

注意 是0<=P

Output

Sample Input


Sample Output


HINT

 30%的数据保证, n ≤ 2. 50%的数据保证, n ≤ 5. 100%的数据保证, n , l, m≤ 10.

Source

[ Submit][ Status][ Discuss]




【分析】

AC自动机+矩阵乘法

本来概率这么奇奇怪怪的东西是不能暴算的...但是精度要求很低,矩阵乘法暴算2^50基本可以得到解。




【代码】

//bzoj 1444 [Jsoi2009]有趣的游戏
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define M(a) memset(a,0,sizeof a)
#define fo(i,j,k) for(int i=j;i<=k;i++)
using namespace std;
const int mxn=105;
char s[mxn];
queue <int> q;
double g[mxn];
int n,m,len,num=1;
struct matrix
{
    double a[mxn][mxn];
    matrix operator * (const matrix &x) const
    {
        matrix res;
        fo(i,1,num)
          fo(j,1,num)
          {
              res.a[i][j]=0.0;
              fo(k,1,num)
                res.a[i][j]+=a[i][k]*x.a[k][j];
          }
        return res;
    }
}ans,S;
struct AC_auto
{
    int son[15],fail,dang;
}a[mxn];
inline void trie(int id)
{
    int x=1;
    scanf("%s",s+1);
    fo(i,1,len)
    {
        int c=s[i]-'A'+1;
        if(!a[x].son[c])
          a[x].son[c]=(++num);
        x=a[x].son[c];
    }
    a[x].dang=id;
}
inline void build()
{
    fo(i,1,m)
    {
        int x=a[1].son[i];
        if(x) q.push(x),a[x].fail=1;
        else a[1].son[i]=1;
    }
    while(!q.empty())
    {
        int x=q.front();q.pop();
        int fail=a[x].fail;
        fo(i,1,m)
        {
            int y=a[x].son[i];
            if(!y) a[x].son[i]=a[fail].son[i];
            else q.push(y),a[y].fail=a[fail].son[i];
        }
    }
}
int main()
{
    int i,j,k,u,v,now=0;
    scanf("%d%d%d",&n,&len,&m);
    fo(i,1,m)
    {
        scanf("%d%d",&u,&v);
        g[i]=(double)u/(double)v;
    }
    fo(i,1,n) trie(i);build();
    fo(i,1,num)
      fo(j,1,m) if(a[i].son[j])
        ans.a[i][a[i].son[j]]+=g[j];
    fo(i,1,num) if(a[i].dang)
    {
        fo(j,1,num) ans.a[i][j]=0.0;
        ans.a[i][i]=1.0;
    }
    int czy=50;
    while(czy--)
    {
        S=ans;M(ans.a);
        ans=S*S;
    }
    fo(i,1,num) g[a[i].dang]=ans.a[1][i];
    fo(i,1,n) printf("%.2lf\n",g[i]);
    return 0;
}
/*
3 4 2
1 2
1 2
AABA
ABAA
BAAA
*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值