[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;
}
原文地址:https://www.cnblogs.com/crashed/p/13777006.html