• 2016ACM/ICPC亚洲区沈阳站H


    http://acm.hdu.edu.cn/showproblem.php?pid=5955

    题意:给你长度为l的n组数,每个数1-6,每次扔色子,问你每个串第一次被匹配的概率是多少

    题解:先建成ac自动机构造fail数组,然后因为fail指针可能向前转移所以不能不能直接递推dp,需要高斯消元解方程,对于节点i,假设不是结束点而且能转移到它的点有a1,a2...an,那么dp[i]=1/6*dp[a1]+1/6*dp[a2]+...+1/6*a[n],然后我们可以列出n个方程,高斯消元然后找到每个串结尾点的概率就是答案了

    //#pragma comment(linker, "/stack:200000000")
    //#pragma GCC optimize("Ofast,no-stack-protector")
    //#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
    //#pragma GCC optimize("unroll-loops")
    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define mp make_pair
    #define pb push_back
    #define pi acos(-1.0)
    #define ll long long
    #define vi vector<int>
    #define mod 1000000007
    #define C 0.5772156649
    #define ls l,m,rt<<1
    #define rs m+1,r,rt<<1|1
    #define pil pair<int,ll>
    #define pli pair<ll,int>
    #define pii pair<int,int>
    #define cd complex<double>
    #define ull unsigned long long
    #define base 1000000000000000000
    #define fio ios::sync_with_stdio(false);cin.tie(0)
    
    using namespace std;
    
    const double g=10.0,eps=1e-12;
    const int N=100+10,maxn=20000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f;
    
    int l;
    double a[N][N],ans[N];
    void gauss(int n)
    {
        for(int i=1;i<n;i++)
        {
            if(a[i][i]==0)
            {
                int id=0;
                for(int j=i+1;j<=n;j++)
                    if(a[j][i]!=0)
                        id=j;
                for(int j=i;j<=n+1;j++)
                    swap(a[i][j],a[id][j]);
            }
            for(int j=i+1;j<=n;j++)
            {
                double t=a[j][i]/a[i][i];
                for(int k=i;k<=n+1;k++)
                    a[j][k]-=(a[i][k]*t);
            }
        }
    //    for(int i=1;i<=n;i++)
    //    {
    //        for(int j=1;j<=n+1;j++)
    //            printf("%.12f ",a[i][j]);
    //        puts("");
    //    }
        for(int i=n;i>=1;i--)
        {
            for(int j=i+1;j<=n;j++)
                a[i][n+1]-=ans[j]*a[i][j];
            ans[i]=a[i][n+1]/a[i][i];
        }
    }
    char s[N];
    struct ACM{
        int root,tot;
        int Next[N][10],fail[N],End[N];
        int newnode()
        {
            memset(Next[tot],-1,sizeof Next[tot]);
            End[tot]=0;
            return tot++;
        }
        void init()
        {
            tot=0;
            root=newnode();
        }
        void ins(int i)
        {
            int now=root;
            for(int i=0,x;i<l;i++)
            {
                scanf("%d",&x);x--;
                if(Next[now][x]==-1)
                    Next[now][x]=newnode();
                now=Next[now][x];
            }
            End[now]=i;
        }
        void build()
        {
            queue<int>q;
            fail[root]=root;
            for(int i=0;i<6;i++)
            {
                if(Next[root][i]==-1)Next[root][i]=root;
                else
                {
                    fail[Next[root][i]]=root;
                    q.push(Next[root][i]);
                }
            }
            while(!q.empty())
            {
                int now=q.front();
                q.pop();
                if(End[fail[now]])End[now]=End[fail[now]];
                for(int i=0;i<6;i++)
                {
                    if(Next[now][i]==-1)Next[now][i]=Next[fail[now]][i];
                    else
                    {
                        fail[Next[now][i]]=Next[fail[now]][i];
                        q.push(Next[now][i]);
                    }
                }
            }
        }
        void solve()
        {
            memset(a,0,sizeof a);
            a[1][tot+1]=-1.0;
            for(int i=0;i<tot;i++)
            {
                a[i+1][i+1]=-1.0;
                if(End[i])continue;
                for(int j=0;j<6;j++)a[Next[i][j]+1][i+1]+=1.0/6;
            }
    //        for(int i=1;i<=tot;i++)
    //        {
    //            for(int j=1;j<=tot+1;j++)printf("%.5f ",a[i][j]);
    //            puts("");
    //        }
            gauss(tot);
            bool ok=0;
            for(int i=0;i<tot;i++)
            {
                if(End[i])
                {
                    if(!ok)printf("%.6f",ans[i+1]);
                    else printf(" %.6f",ans[i+1]);
                    ok=1;
                }
            }
            puts("");
        }
    }ac;
    int main()
    {
        int T;scanf("%d",&T);
        while(T--)
        {
            ac.init();
            int n;
            scanf("%d%d",&n,&l);
            for(int i=0;i<n;i++)ac.ins(i+1);
            ac.build();
            ac.solve();
        }
        return 0;
    }
    /***********************
    1
    2 2
    1 1
    2 1
    ***********************/
    View Code
  • 相关阅读:
    android的dex,odex,oat,vdex,art文件格式
    windows写时复制处理流程
    .NET 6中读取配置文件内容
    .net core 配置文件
    C# 格式化json
    .net 安全
    07. 图像的翻转、旋转、仿射变换、透视变换
    05. 绘制基本的图像
    03. Pillow包解决opencv中文乱码
    08. 滤波(卷积、均值、高斯、中值、双边滤波)
  • 原文地址:https://www.cnblogs.com/acjiumeng/p/8988446.html
Copyright © 2020-2023  润新知