• [HDU6848]Expectation


    题目

    校内赛的改编题目,题意基本与[HDU6848]Expectation相同。

    分析

    首先,不难发现,本题就是求所有不同的操作序列的距离和,最后乘上 (frac{1}{n!2^n}) 的概率就是答案。

    于是考虑如何求这个距离和。这里有两种方法:

    方法 1

    本题的贡献显然是可以拆分的。我们只需要计算 (x_{i+1}-x_i) 会被算几次就好了。

    显然每一段的次数仅与数量 (n) 和段数 (i) 相关,因此可以定义状态:

    (f(n,i)) :有 (n)(n+1) 洞时,(x_{i+1}-x_i) 的计算次数。

    先画出示意图如下,我们考虑求第 (3) 段的次数。

       o     o     o
       
    U     U     U     U
    |--|--|--|--|--|--|
     1  2  3  4  5  6
    

    其中 o 表示球,U 表示洞。下方标注了每一段。

    那么我们随便让一个球进洞:

       o     o     o
            /
    U     U     U     U
    |--|--|--|--|--|--|
     1  2  3  4  5  6
    --------Then-------
       o           o
               
    U           U     U
    |--|--------|--|--|
     1  2        3  4
    

    可以发现,现在球和洞各减少了一个,并且原先的第 (3) 段现在被包在了第 (2) 段里面。因此这样的话会转移到 (f(n-1,i-1)) ,仅有一种情况。

    再考虑剩下两种情况:

       o     o     o
         
    U     U     U     U
    |--|--|--|--|--|--|
     1  2  3  4  5  6
    --------Then-------
             o     o
       
    U           U     U
    |--------|--|--|--|
     1        2  3  4
    

    现在它转移到了 (f(n-1,i-2)) 里面,对应了 (i-1) 种转移的情况。

       o     o     o
                  /
    U     U     U     U
    |--|--|--|--|--|--|
     1  2  3  4  5  6
    --------Then-------
       o     o      
                  
    U     U           U
    |--|--|--|--------|
     1  2  3  4
    

    现在它转移到了 (f(n-1,i)) 里面,对应了 (2n-i) 种转移的情况。

    接着考虑当前这一步带来的次数。当我们将 (i+1) 移到 (i) 里面(或者 (i) 移到 (i+1) 里面)的时候,我们就会带来 1 次的贡献,总共就会带来 ((i-1)! imes 2^{i-1}) 的贡献。

    因此可以得到转移:

    [f(n,i)=(i-1)f(n-1,i-2)+f(n-1,i-1)+(2n-i)f(n-1,i)+(i-1)! imes 2^{i-1} ]

    于是这个就可以 (O(n^2)) 预处理了。最后每次 (O(n)) 扫一遍就可以计算答案了。

    方法 2

    该方法仅针对改编后的题目,仅可以通过一次询问的情况

    方案 2.1:请参考 zxy 巨佬的博客

    方案 2.2:

    这是本人口胡的做法,并且还没有优化出来

    可以发现,最后只有一个洞会留下来。我们可以枚举这个洞,这样左右两边就是独立的,且洞数恰好等于球数。

    因此可以定义 (f(i,j)) 表示区间 ([i,j]) 被消完的操作序列的距离和,且 (i)(j) 的奇偶性不同

    (i)(j) 奇的转移为例。我们可以枚举 (i) 进的洞 (k) ,那么 ((i+1,k-1)) 必须在 (i) 被操作之前被消完。而 ((k+1,j)) 的操作则任意。可以发现我们得到了两个子问题。

    注意到合法序列的数量仅与区间长度有关。因此设 (g(i)) 表示长度为 (i) 的区间的合法操作序列的个数。令 (L)([i,j]) 中球的个数, (l)([i,k]) 中球的个数。可以得到转移:

    [f(i,j)=sum_{k} inom{L}{l} imes (g(L-l-1)f(i+1,k-1)+g(l)g(L-l-1)(x_k-x_i)+g(l)f(k+1,j)) ]

    由于是统计序列,所以需要乘上组合数计算序列的形态。

    这样转移是 (O(n^3)) 的,如果有会优化的请一定要告诉我。

    小结:

    方法 1 的关键在于拆分贡献独立计算提取影响状态的信息

    方法 2 ,作为一个未通过的做法......

    代码

    #include <cstdio>
    
    typedef long long LL;
    
    const int mod = 998244353;
    const int MAXN = 3005;
    
    template<typename _T>
    void read( _T &x )
    {
    	x = 0; char s = getchar(); int f = 1;
    	while( s < '0' || '9' < s ) { f = 1; if( s == '-' ) f = -1; s = getchar(); }
    	while( '0' <= s && s <= '9' ) { x = ( x << 3 ) + ( x << 1 ) + ( s - '0' ); s = getchar(); }
    	x *= f;
    }
    
    template<typename _T>
    void write( _T x )
    {
    	if( x < 0 ) putchar( '-' ), x = -x;
    	if( 9 < x ) write( x / 10 );
    	putchar( x % 10 + '0' );
    }
     
    int f[MAXN][MAXN << 1];
    
    int X[MAXN];
    int N, inv;
    
    int Qkpow( int, int );
    int Inv( const int a ) { return Qkpow( a, mod - 2 ); }
    int Sub( int x, int v ) { return x < v ? x + mod - v : x - v; }
    int Mul( LL x, int v ) { x *= v; if( x >= mod ) x %= mod; return x; }
    int Add( int x, int v ) { return x + v >= mod ? x + v - mod : x + v; }
    int Fix( const int a ) { return ( a % mod + mod ) % mod; }
    
    int Qkpow( int base, int indx )
    {
    	int ret = 1;
    	while( indx )
    	{
    		if( indx & 1 ) ret = Mul( ret, base );
    		base = Mul( base, base ), indx >>= 1;
    	}
    	return ret;
    }
    
    void Init( const int n )
    {
    	int coe = 1;
    	f[1][1] = f[1][2] = 1;
    	for( int i = 2 ; i <= n ; i ++ )
    	{
    		coe = Mul( 2 * ( i - 1 ), coe );
    		for( int j = 1 ; j <= 2 * i ; j ++ )
    		{
    			f[i][j] = Add( f[i - 1][j - 1], Mul( f[i - 1][j], 2 * i - j ) );
    			if( j >= 2 ) f[i][j] = Add( f[i][j], Mul( f[i - 1][j - 2], j - 1 ) );
    			f[i][j] = Add( f[i][j], coe );
    		}
    	}
    	inv = Inv( Mul( coe, 2 * n ) );
    }
    
    int main()
    {
    	read( N ), Init( N );
    	for( int i = 1 ; i <= 2 * N + 1 ; i ++ ) read( X[i] );
    
    	int ans = 0;
    	for( int i = 1 ; i <= N ; i ++ )
    		ans = Add( ans, Add( Mul( Fix( X[i << 1] - X[( i << 1 ) - 1] ), f[N][( i << 1 ) - 1] ),
    							 Mul( Fix( X[( i << 1 ) + 1] - X[i << 1] ), f[N][i << 1] ) ) );
    	write( Mul( ans, inv ) ), putchar( '
    ' );
    	return 0;
    }
    
  • 相关阅读:
    PAT (Advanced Level) 1060. Are They Equal (25)
    PAT (Advanced Level) 1059. Prime Factors (25)
    PAT (Advanced Level) 1058. A+B in Hogwarts (20)
    PAT (Advanced Level) 1057. Stack (30)
    PAT (Advanced Level) 1056. Mice and Rice (25)
    PAT (Advanced Level) 1055. The World's Richest (25)
    PAT (Advanced Level) 1054. The Dominant Color (20)
    PAT (Advanced Level) 1053. Path of Equal Weight (30)
    PAT (Advanced Level) 1052. Linked List Sorting (25)
    PAT (Advanced Level) 1051. Pop Sequence (25)
  • 原文地址:https://www.cnblogs.com/crashed/p/13777006.html
Copyright © 2020-2023  润新知