zoukankan      html  css  js  c++  java
  • Solution -「LOCAL」客星璀璨之夜

    (mathcal{Description})

      OurOJ.

      给定坐标轴上的 (2n+1) 个坐标 (x_1,x_2,cdots,x_{2n+1}),其中偶数下标的位置是一个小球,奇数下标的位置是一个球洞。每次操作随机选择一个小球,并随机让它向左或向右滚入临近的球洞,该球洞被填满,视作平地。求所有球进洞后,球滚动总距离的期望。对 (998244353) 取模。

      (nle3000)

    (mathcal{Solution})

      显然,(n) 个球进洞的总方案为 (2^nn!),记为 (g(n))。现只需要计算所有方案的滚动距离之和。坐标实际位置并不重要,考虑一段形如 (x_ileftrightarrow x_{i+1}) 的距离在多少种方案中贡献。

      贡献次数显然仅与 (n) 和位置 (i) 有关。令 (f(i,j)) 表示仅有 (i) 个球(和 (i+1) 个洞)时,(x_jleftrightarrow x_{j+1}) 的贡献次数。转移时,考虑当前局面第一次操作:

    • (x_j)(x_{j+1}) 配对消失,贡献次数为剩下 (i-1) 个球撞完的总方案数,即 (g(n-1)),并且 (x_jleftrightarrow x_{j+1}) 这一段被纳入了(x_{j-1}leftrightarrow x_{j+2}),转移需要让坐标前移一位,那么 (f(i,j) leftarrow f(i,j)+g(i-1)+f(i-1,j-1))

    • 操作 (j) 前面的球,有 (j-1) 种等价操作方式,当前这段没有贡献,坐标向前两位,即 (f(i,j) leftarrow f(i,j)+(j-1)f(i-1,j-2))

    • 操作 (j+1) 后面的球,有 (2i-j) 种等价操作方式,当前这段还是没有贡献,坐标也没有影响,即 (f(i,j) leftarrow f(i,j)+(2i-j)f(i-1,j))

      综上:

    [ f(i,j)=g(i-1)+f(i-1,j-1)+(j-1)f(i-1,j-2)+(2i-j)f(i-1,j) ]

      答案显而易见:

    [ frac{sum_{i=1}^{2n}(x_{i+1}-x_i)f(n,i)}{g(n)} ]

      复杂度 (mathcal O(n^2))

    (mathcal{Code})

    /* Clearink */
    
    #include <cstdio>
    
    inline int rint () {
    	int x = 0, f = 1; char s = getchar ();
    	for ( ; s < '0' || '9' < s; s = getchar () ) f = s == '-' ? -f : f;
    	for ( ; '0' <= s && s <= '9'; s = getchar () ) x = x * 10 + ( s ^ '0' );
    	return x * f;
    }
    
    template<typename Tp>
    inline void wint ( Tp x ) {
    	if ( x < 0 ) putchar ( '-' ), x = ~ x + 1;
    	if ( 9 < x ) wint ( x / 10 );
    	putchar ( x % 10 ^ '0' );
    }
    
    const int MAXN = 3000, MOD = 998244353;
    int n, m, x[MAXN * 2 + 5], g[MAXN + 5], f[MAXN + 5][MAXN * 2 + 5];
    
    inline int& addeq ( int& a, const int b ) {
    	return ( a += b ) < MOD ? a : a -= MOD;
    }
    
    inline int qkpow ( int a, int b, const int p = MOD ) {
    	int ret = 1;
    	for ( ; b; a = 1ll * a * a % p, b >>= 1 ) ret = 1ll * ret * ( b & 1 ? a : 1 ) % p;
    	return ret;
    }
    
    int main () {
    //	freopen ( "stars.in", "r", stdin );
    //	freopen ( "stars.out", "w", stdout );
    	m = ( n = rint () ) << 1 | 1;
    	for ( int i = 1; i <= m; ++ i ) x[i] = rint ();
    	g[0] = 1;
    	for ( int i = 1; i <= n; ++ i ) {
    		g[i] = 2ll * i * g[i - 1] % MOD;
    		for ( int j = 1; j <= i << 1; ++ j ) {
    			addeq ( addeq ( addeq ( addeq ( f[i][j], g[i - 1] ), f[i - 1][j - 1] ),
    				( j - 1ll ) * f[i - 1][j - 2 < 0 ? 0 : j - 2] % MOD ),
    				( 2ll * i - j ) * f[i - 1][j] % MOD
    			);
    		}
    	}
    	int ans = 0;
    	for ( int i = 1; i <= n << 1; ++ i ) {
    		addeq ( ans, 1ll * ( x[i + 1] - x[i] ) * f[n][i] % MOD );
    	}
    	wint ( 1ll * ans * qkpow ( g[n], MOD - 2 ) % MOD ), putchar ( '
    ' );
    	return 0;
    }
    

    (mathcal{Details})

      考场上想的统计每一对 (i) 球撞 (j) 洞的出现次数,但这个涉及到多类方案的交叉安排,而且方案间有依赖关系……就死掉啦。

      还有,暴力打半天过不了样例,手玩了一下发现距离贡献没乘方案数 qwq。

  • 相关阅读:
    Machine learning 第8周编程作业 K-means and PCA
    Machine learning 第7周编程作业 SVM
    Machine learning第6周编程作业
    Machine learning 第5周编程作业
    小M的作物 最小割最大流
    k-近邻算法 python实现
    编辑距离 区间dp
    Machine learning第四周code 编程作业
    MDK5报错missing closing quote
    HDU 5512
  • 原文地址:https://www.cnblogs.com/rainybunny/p/13776378.html
Copyright © 2011-2022 走看看