zoukankan      html  css  js  c++  java
  • [UOJ211][UER #6]逃跑

    题意:从原点出发,走(n)次,每次往四个方向中随机一个走,走每个方向有个概率,求所有方案走到过的点数的方差。

    题解:orz kczno1

    (E*all=sum (a_i-avg)^2*all=sum a_i^2-2*sum a_i*avg+avg^2*all*all)。把(avg=frac{sum a_i}{all})代入,可以发现要求的就是(sum a_i)(sum a_i^2)。以下为了方便求概率。

    (f_{i,x,y})为走了(i)步第一次走到(x,y)的概率,(g_{i,x,y})为走了(i)步最后在(x,y)的概率,(g)可以暴力DP,(f)(g)容斥一下就行了。(sum a_i)显然可以拆成对于每个点,求出经过它的概率并求和,就是(sum f)

    考虑怎样求(sum a_i^2)。可以用类似管道取珠的方法,把(x^2)拆成(inom{x}{2}*2+x),那么只要求(sum inom{x}{2})。设(h_{i,x,y})为走了(i)步第一次走到某个点(a,b)并且之前走到过(a-x,b-y)的概率和,那么(h_{i,x,y}=sum_{j<i,a,b}f_{j,a,b}f_{i-j,x,y}-sum_{j<i}h_{j,-x,-y}f_{i-j,x,y}),减掉的是第一次到达某个点(a,b)之前到达过(a+x,b+y)的概率。

    再加一些卡常就uojrk2了。注意用16次一取膜优化的时候要保证每一次加的都为非负数,否则要改为(signed) long long并且改为8次一取膜。一开始因为这个WA飞了。

    #include<bits/stdc++.h>
    using namespace std;
    const int mod = 998244353;
    const int N = 110;
    typedef long long ll;
    
    int qpow(int a, int b) {
      int ret = 1;
      while(b) {
        if(b & 1) {
          ret = 1ll * ret * a % mod;
        }
        a = 1ll * a * a % mod, b >>= 1;
      }
      return ret;
    }
    
    int n, w[4], tt = 0, f[N][N * 2][N * 2], g[N][N * 2][N * 2], h[N][N * 2][N * 2], sf[N], dx[4] = {0, 0, -1, 1}, dy[4] = {1, -1, 0, 0}, s1 = 0, s2 = 0;
    
    int main() {
      cin >> n;
      for(int i = 0; i < 4; i++) {
        cin >> w[i], tt += w[i];
      }
      for(int i = 0; i < 4; i++) {
        w[i] = 1ll * w[i] * qpow(tt, mod - 2) % mod;
      }
      f[0][N][N] = g[0][N][N] = sf[0] = 1;
      for(int i = 1; i <= n; i++)
        for(int x = -i; x <= i; x++)
          for(int y = -i; y <= i; y++) {
            if(abs(x) + abs(y) > i) {
              continue;
            }
            ll sum = 0;
            for(int k = 0; k < 4; k++) {
              sum += 1ll * g[i - 1][x - dx[k] + N][y - dy[k] + N] * w[k];
            }
            g[i][x + N][y + N] = sum % mod;
            sum = g[i][x + N][y + N];
            for(int k = 0; k < i; k++) {
              sum -= 1ll * f[k][x + N][y + N] * g[i - k][N][N];
              if((k & 7) == 7) {
                sum %= mod;
              }
            }
            f[i][x + N][y + N] = (sum % mod + mod) % mod;
            sf[i] = (sf[i] + f[i][x + N][y + N]) % mod;
            sum = 0;
            for(int k = 0; k < i; k++) {
              sum += 1ll * (sf[k] - h[k][-x + N][-y + N]) * f[i - k][x + N][y + N];
              if((k & 7) == 7) {
                sum %= mod;
              }
            }
            h[i][x + N][y + N] = (sum % mod + mod) % mod;
          }
      for(int i = 0; i <= n; i++) {
        s1 = (s1 + sf[i]) % mod;
      }
      for(int i = 0; i <= n; i++)
        for(int x = -i; x <= i; x++)
          for(int y = -i; y <= i; y++) {
            if(abs(x) + abs(y) > i) {
              continue;
            }
            s2 = (s2 + h[i][x + N][y + N]) % mod;
          }
      tt = qpow(tt, n);
      s1 = 1ll * s1 * tt % mod, s2 = 1ll * s2 * tt % mod;
      cout << ((1ll * tt * (2ll * s2 + s1) - 1ll * s1 * s1) % mod + mod) % mod;
      return 0;
    }
    
    
    
  • 相关阅读:
    CAD输出图至Word
    win7激活工具
    IP地址出现错误
    x%内存可用的问题解决
    第一次来到博客园
    ++x和x++
    标准输入流输出流以及错误流
    关于main函数的参数
    hdu1465 动态规划
    静态变量(static)的特点
  • 原文地址:https://www.cnblogs.com/gczdajuruo/p/10935382.html
Copyright © 2011-2022 走看看