• 洛谷 3706 [SDOI2017]硬币游戏——思路


    题目:https://www.luogu.org/problemnew/show/P3706

    题解:https://blog.csdn.net/gjghfd/article/details/80355976

    令 ( p_x ) 表示哪个串都没在结尾匹配上的概率,那么在 ( p_x ) 的基础上再出现 m 个特定的字符就能拼出任意一个串了。

    但是在再出现 m 个字符的过程中可能已经匹配上了某个串,比如 HTT 和 THT ,想在 ( p_x ) 的基础上出现 THT 拼出第二个串,但如果是 ( p_x ) 里长成 HT 样子的串的话,再出现一个 T 就会以第一个串为结尾结束了。

    每个字符出现的概率是一样的。所以可以认为 ( p_x ) 里出现形如 HT 或者 ***HT ( ***HT 没有匹配上一个串) 之类的串的概率是 ( ( frac{1}{2} )^2 ) 。不过不太知道为什么是这样。

    所以就有 ( p_x*frac{1}{2^m} = p_i+sumlimits_{j=1}^{n}p_jsumlimits_{l in L_{i,j}}frac{1}{2^{m-l}} ) ,其中 ( L_{i,j} ) 表示 i 的前缀与 j 的后缀可以匹配的长度的集合。

    还有一个式子就是 ( sumlimits_{i=1}^{n}p_i = 1 ) ,就能高斯消元了。

    可以用哈希求 ( L_{i,j} ) 。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define ll long long
    #define db long double
    using namespace std;
    const int N=305,b1=1e9+7,b2=10007,m1=1e9+9,m2=993244853;
    int n,m,pw[N][2];
    bool b[N][N]; db bin[N],a[N][N];
    struct Node{
      int v0,v1;
      Node(int a=0,int b=0):v0(a),v1(b) {}
      bool operator== (const Node &b)const
      {return v0==b.v0&&v1==b.v1;}
    }h[N][N];
    Node get_h(int i,int j)
    {
      int r0=(h[i][m].v0-(ll)h[i][j-1].v0*pw[m-j+1][0])%m1;
      int r1=(h[i][m].v1-(ll)h[i][j-1].v1*pw[m-j+1][1])%m2;
      if(r0<0)r0+=m1; if(r1<0)r1+=m2;
      return Node(r0,r1);
    }
    void solve()
    {
      pw[0][0]=pw[0][1]=1;
      for(int i=1;i<=m;i++)
        {
          pw[i][0]=(ll)pw[i-1][0]*b1%m1;
          pw[i][1]=(ll)pw[i-1][1]*b2%m2;
        }
      for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
          {
        h[i][j].v0=((ll)h[i][j-1].v0*b1+b[i][j])%m1;
        h[i][j].v1=((ll)h[i][j-1].v1*b2+b[i][j])%m2;
          }
      for(int i=1;i<=n;i++)a[i][0]=-bin[m];//a[][0]:px
      a[0][n+1]=1;for(int i=1;i<=n;i++)a[0][i]=1;//a[0][]:sum=1
      for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
          for(int k=1;k<=m;k++)
        if(h[i][k]==get_h(j,m-k+1)) a[i][j]+=bin[m-k];
    }
    void gauss()
    {
      for(int i=0;i<=n;i++)
        {
          int bh=i;
          for(int j=i+1;j<=n;j++)
        if(fabs(a[j][i])>fabs(a[bh][i]))bh=j;
          for(int j=i;j<=n+1;j++)swap(a[i][j],a[bh][j]);
          db sl=a[i][i];
          for(int j=i;j<=n+1;j++)a[i][j]/=sl;//
          for(int j=1;j<=n;j++)
        if(j!=i&&fabs(a[j][i]))
          {
            sl=a[j][i];
            for(int k=i;k<=n+1;k++)a[j][k]-=sl*a[i][k];
          }
        }
    }
    int main()
    {
      scanf("%d%d",&n,&m); char ch[N];
      bin[0]=1;for(int i=1;i<=m;i++)bin[i]=bin[i-1]/2;
      for(int i=1;i<=n;i++)
        {
          scanf("%s",ch+1);
          for(int j=1;j<=m;j++)b[i][j]=(ch[j]=='H');
        }
      solve(); gauss();
      for(int i=1;i<=n;i++)
        printf("%.10Lf
    ",a[i][n+1]);
      return 0;
    }
  • 相关阅读:
    徐汉彬:Web系统大规模并发——电商秒杀与抢购
    编程语言十一月份排行
    windows C 与 linux C区别?
    inux 下c/c++ 连接mysql数据库全过程-----已经通过验证
    MySql可视化工具MySQL Workbench使用教程
    C语言连接数据库
    C语言连接MySql数据库
    C语言位运算
    python-函数
    python2.x和python3.x共存
  • 原文地址:https://www.cnblogs.com/Narh/p/10407245.html
Copyright © 2020-2023  润新知