Live2D

Solution -「AGC 012F」「AT 2366」Prefix Median

Description

  Link.

  给定序列 {a2n1},将 {a2n1} 按任意顺序排列后,令序列 bi 为前 2i1 个数的中位数。求 {bn} 的个数,对 109+7 取模。

  n50

Solution

  {bn} 有一个很 naive 的性质:bn 是常数,是 {a2n1} 的中位数。

  考虑扩展这一性质,从后往前,bi+1 所对应的 a 序列删去两个数后就得到 bi 所对应的序列。显然,bi 要么是 bi+1 在新序列的前驱或后记,要么不变。

  形式地,有性质:

(i[1,n))(j[1,n])(bi<bj<bi+1bi+1<bj<bi)

  接着,考虑到中位数本身的性质,将 {a2n+1} 升序排列后,可以确定每个 bi 的范围:

aibia2ni

  那么设状态 f(i,j,k) 表示确定前 i 位,中位数左边有 j 个数可用,右边有 k 个数可用的方案数。转移就……看代码吧 www~

Code

#include <cstdio>
#include <algorithm>

const int MAXN = 50, MAXM = 100, MOD = 1e9 + 7;
int n, m, a[MAXM + 5], f[2][MAXM + 5][MAXM + 5];

inline void addeq ( int& a, const int b ) { if ( ( a += b ) >= MOD ) a -= MOD; }

int main () {
	scanf ( "%d", &n ), m = 2 * n;
	for ( int i = 1; i < m; ++ i ) scanf ( "%d", &a[i] );
	std::sort ( a + 1, a + m );
	f[0][0][0] = 1;
	for ( int i = n, t = 0; i > 1; -- i, t ^= 1 ) {
		bool dl = a[i] ^ a[i - 1], dr = a[m - i + 1] ^ a[m - i];
		for ( int j = 0; j < m; ++ j ) {
			for ( int k = 0; k < m; ++ k ) {
				int& cur = f[t][j][k];
				if ( ! cur ) continue;
				addeq ( f[t ^ 1][j + dl][k + dr], cur );
				for ( int p = 0; p < j + dl; ++ p ) addeq ( f[t ^ 1][p][k + dr + 1], cur );
				for ( int p = 0; p < k + dr; ++ p ) addeq ( f[t ^ 1][j + dl + 1][p], cur );
				cur = 0;
			}
		}
	}
	int ans = 0;
	for ( int i = 0; i < m; ++ i ) {
		for ( int j = 0; j < m; ++ j ) {
			addeq ( ans, f[n & 1 ^ 1][i][j] );
		}
	}
	printf ( "%d\n", ans );
	return 0;
}
posted @   Rainybunny  阅读(134)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示