zoukankan      html  css  js  c++  java
  • LOJ 2552 「CTSC2018」假面——DP

    题目:https://loj.ac/problem/2552

    70 分就是 f[i][j] 表示第 i 个人血量为 j 的概率。这部分是 O( n*Q ) 的;g[i][j][0/1] 表示询问的人中,前/后 i 个人,存活 j 个人的概率。做 g[ ][ ] 是 n^2 的,算答案是 n3 的。

    考虑 g[ i ] 表示询问的人中有 i 个存活的概率。因为每个人加入 g[ ] 的顺序无关,所以可以每次 O(n) 地从g[ ] 里剔除第 i 个人的贡献。

    令第 i 个人不存活的概率是 u ,存活的概率是 v 。

    当初的转移是 g[ i ] * u -> g'[ i ] , g[ i ] * v -> g'[ i+1 ] ,所以现在可以倒着做:g[ i ] = g'[ i+1 ] / v , g'[ i ] -= g[ i ] ,或者正着做:g[ i ] = g'[ i ] / u , g'[ i+1 ] -= g[ i ] * v 。

    发现如果 u=0 ,那么 g[ i ] 的值只体现在了 g'[ i+1 ] 里;所以倒着做。如果 v=0 就正着做。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    using namespace std;
    int rdn()
    {
      int ret=0;bool fx=1;char ch=getchar();
      while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
      while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
      return fx?ret:-ret;
    }
    const int N=205,M=105,mod=998244353;
    int upt(int x){while(x>=mod)x-=mod;while(x<0)x+=mod;return x;}
    int pw(int x,int k)
    {int ret=1;while(k){if(k&1)ret=(ll)ret*x%mod;x=(ll)x*x%mod;k>>=1;}return ret;}
    
    int n,a[N],f[N][M],g[N],tp[N],h[N],q[N],inv[N];
    int main()
    {
      n=rdn(); inv[1]=1;
      for(int i=2;i<=n;i++)inv[i]=(ll)upt(-mod/i)*inv[mod%i]%mod;
      for(int i=1,d;i<=n;i++)
        { a[i]=rdn();f[i][a[i]]=1;}
      int Q=rdn(),op,x,u,v;
      while(Q--)
        {
          op=rdn();
          if(!op)
        {
          x=rdn();u=rdn();v=rdn();
          u=(ll)u*pw(v,mod-2)%mod;
          for(int j=1;j<=a[x];j++)
            {
              f[x][j-1]=(f[x][j-1]+(ll)f[x][j]*u)%mod;
              f[x][j]=(ll)f[x][j]*upt(1-u)%mod;
            }
          if(!f[x][a[x]])a[x]--;
        }
          else
        {
          x=rdn(); int tl=0;
          for(int i=1;i<=x;i++)
            q[++tl]=rdn();
          g[0]=1;for(int i=1;i<=tl;i++)g[i]=0;
          for(int i=1;i<=tl;i++)
            {
              u=f[q[i]][0]; v=upt(1-u);
              for(int j=i;j>=0;j--)
            {
              g[j]=(ll)g[j]*u%mod;
              if(j)g[j]=(g[j]+(ll)g[j-1]*v)%mod;
            }
            }
          for(int i=1;i<=tl;i++)
            {
              u=f[q[i]][0]; v=upt(1-u);
              memcpy(tp,g,sizeof g);
              if(!u)
            {
              int iv=pw(v,mod-2);
              for(int j=tl-1;j>=0;j--)
                {
                  h[j]=(ll)tp[j+1]*iv%mod;
                  tp[j]=upt((tp[j]-(ll)u*h[j])%mod);
                }
            }
              else
            {
              int iu=pw(u,mod-2);
              for(int j=0;j<tl;j++)
                {
                  h[j]=(ll)tp[j]*iu%mod;
                  tp[j+1]=upt((tp[j+1]-(ll)v*h[j])%mod);
                }
            }
              int ans=0;
              for(int j=0;j<tl;j++)
            ans=(ans+(ll)h[j]*v%mod*inv[j+1])%mod;
              printf("%d ",ans);
            }
          puts("");
        }
        }
      for(int i=1;i<=n;i++)
        {
          int ans=0;
          for(int j=0;j<=a[i];j++)
        ans=(ans+(ll)j*f[i][j])%mod;
          printf("%d ",ans);
        }
      puts(""); return 0;
    }
  • 相关阅读:
    Flink读取Kafka数据,进行汇总
    Flink集成到CDH上,并运行一个例子
    CDH6.2安装配置第三篇:前台页面配置讲解
    LINUX之ntp时间同步服务配置
    Dubbo+Zookeeper(一)Zookeeper初识
    SpringCloud(五)Zuul网关与分布式配置中心
    SpringCloud(四)Hystrix熔断器
    SpringCloud(三)Ribbon与Feign
    SpringCloud(二)服务注册与发现
    多线程与高并发(六) Lock
  • 原文地址:https://www.cnblogs.com/Narh/p/10823577.html
Copyright © 2011-2022 走看看