Live2D

Solution -「LOCAL」客星璀璨之夜

Description

  OurOJ.

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

  n3000

Solution

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

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

  • xjxj+1 配对消失,贡献次数为剩下 i1 个球撞完的总方案数,即 g(n1),并且 xjxj+1 这一段被纳入了xj1xj+2,转移需要让坐标前移一位,那么 f(i,j)f(i,j)+g(i1)+f(i1,j1)

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

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

  综上:

f(i,j)=g(i1)+f(i1,j1)+(j1)f(i1,j2)+(2ij)f(i1,j)

  答案显而易见:

i=12n(xi+1xi)f(n,i)g(n)

  复杂度 O(n2)

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 ( '\n' );
	return 0;
}

Details

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

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

posted @   Rainybunny  阅读(368)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示