P8321 『JROI-4』沈阳大街 2 题解

P8321 『JROI-4』沈阳大街 2 题解

过了好久,终于抽出来时间把这个题写出来了
贴一个大佬的

大佬就是大佬,讲的通俗易懂,我都能看懂
实际上就是将两个合并到一起从大到小排序,这样针对前面每一个数进行dp来做,就是找一下前面有多少跟它颜色不一样,但是还没配对的,一配对,乘的肯定是当前的,因为它小啊

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
#define PII pair<int, int>
#define fast ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define x first
#define y second

const int N = 5010;
int f[2 * N][N];
int cnt[2][2 * N];
#define MOD 998244353
vector<PII> v;

int quick(int a, int b)
{
	int res = 1;
	while(b)
	{
		if(b & 1)
		{
			res *= a;
			res %= MOD;
		}
		a *= a;
		a %= MOD;
		b >>= 1;
	}
	return res;
}
bool cmp(PII a, PII b)
{
	if(a.x != b.x) return a.x > b.x;
	else return a.y > b.y;
}
signed main()
{
	int n;
	cin >> n;
	int x;
	for(int i=1; i<=n; i++)
	{
		cin >> x;
		v.push_back({x, 0});
	}
	for(int i=1; i<=n; i++)
	{
		cin >> x;
		v.push_back({x, 1});
	}
	v.push_back({1e9 + 10, 1e9});

	sort(v.begin(), v.end(), cmp);

	// cout << v[0].x <<endl;
	f[0][0] = 1;

	for(int i=1; i<= 2 * n; i++)
	{
		cnt[1][i] = cnt[1][i-1];
		cnt[0][i] = cnt[0][i-1];
		if(v[i].y) cnt[1][i] ++;
		else cnt[0][i] ++;
	}
	for(int i=1; i<=2 * n; i++)
	{
		int num = cnt[!v[i].y][i];
		f[i][0] = 1;
		for(int j=1; j<=i / 2; j++)//枚举已经配对了多少对
		{
			if(j <= num) f[i][j] = (f[i-1][j - 1] * (num - j + 1) % MOD) * v[i].x % MOD;
			f[i][j] = (f[i][j] + f[i-1][j]) % MOD;
		}
	}

	int res = 1;
	for(int i=1; i<=n; i++) res = res * i % MOD;

	cout << quick(res, MOD - 2) * f[2 * n][n] % MOD<< endl;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值