zoukankan      html  css  js  c++  java
  • BZOJ 4820 [Sdoi2017]硬币游戏 ——期望DP 高斯消元

    做法太神了,理解不了。

    自己想到的是建出AC自动机然后建出矩阵然后求逆计算,感觉可以过$40%$

    用一个状态$N$表示任意一个位置没有匹配成功的概率和。

    每种匹配不成功的情况都是等价的。

    然后我们强制在后面加上长度为m的01串,那么这个串的概率是一定的。

    然后考虑加上的这些字符还能拼成什么串,因为状态$N$的末尾是不确定的。

    如果另外一个串的后缀等于这个串的前缀的话,是可能带来影响的。

    所以计算出影响的概率,然后高斯消元即可。

    然而有一个问题,N的概率最后消出来代表什么意思啊,是指期望的长度吗?

    希望各位dalao不吝赐教。

    #include <map>
    #include <cmath>
    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    #define F(i,j,k) for (int i=j;i<=k;++i)
    #define D(i,j,k) for (int i=j;i>=k;--i)
    #define ll long long
    #define mp make_pair
     
    int n,m,s[305][305],str[605],fail[605];
    char ss[305];
    double a[305][305],pw[305],ans[305];
     
    void kmp()
    {
    //  F(i,1,2*m) printf("%d ",str[i]); printf("
    ");
        str[0]=-1;
        memset(fail,0,sizeof fail);
        for (int i=2,j=0;i<=2*m;++i)
        {
            while (j&&str[i]!=str[j+1]) j=fail[j];
            if (str[j+1]==str[i]) j++;
            fail[i]=j;
        }
    //  F(i,1,2*m) printf("%d ",fail[i]);printf("
    ");
    }
     
    void solve(int x)
    {
        a[x][x]=1;F(i,1,m) str[i]=s[x][i];
        F(y,1,n)// if (y!=x)
        {
            F(i,1,m) str[i+m]=s[y][i]; kmp();
            int now=fail[2*m];
    //      printf("now is %d
    ",now);
            while (now>=m) now=fail[now];
            while (now)
            {
    //          printf("Can %d
    ",now);
                a[x][y]+=pw[m-now];
                now=fail[now];
            }
        }
        a[x][n+1]=-pw[m]; a[x][n+2]=0;
    }
     
    void Gauss()
    {
        F(i,1,n+1)
        {
            int tmp=i;
            F(j,i+1,n+1) if (fabs(a[j][i])>fabs(a[i][i])) tmp=j;
            if (tmp!=i) F(j,1,n+2) swap(a[i][j],a[tmp][j]);
            F(j,1,n+1) if (j!=i)
            {
                double t=a[j][i]/a[i][i];
                F(k,1,n+2) a[j][k]-=t*a[i][k];
            }
    //      F(i,1,n+1){F(j,1,n+2)printf("%.3f ",a[i][j]);printf("
    ");}
        }
        F(i,1,n+1) ans[i]=a[i][n+2]/a[i][i];
        F(i,1,n) printf("%.10lf
    ",ans[i]);
    }
     
    int main()
    {
    //  freopen("in.txt","r",stdin);
        scanf("%d%d",&n,&m);
        pw[0]=1;F(i,1,m)pw[i]=pw[i-1]*0.5;
        F(i,1,n){scanf("%s",ss+1);F(j,1,m) s[i][j]=(ss[j]=='H');}
        F(i,1,n) solve(i);
        F(i,1,n) a[n+1][i]=1; a[n+1][n+2]=1;
    //  F(i,1,n+1){F(j,1,n+2)printf("%.3f ",a[i][j]);printf("
    ");}
        Gauss();
    }
    

      

  • 相关阅读:
    最小二乘拟合(转)good
    会议论文重新投稿算不算侵权?这肯定是所多人都遇到过的问题(转)
    吝啬的国度
    压力单位MPa、Psi和bar之间换算公式
    Oracle建立表空间和用户
    layoutSubviews总结
    C++中出现的计算机术语4
    445port入侵具体解释
    hdu
    ORM框架
  • 原文地址:https://www.cnblogs.com/SfailSth/p/6737641.html
Copyright © 2011-2022 走看看