【组合数学】建设城市

129 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第16天,点击查看活动详情

[NOI Online #2 入门组] 建设城市

题目描述

球球是一位建筑师。一天,他收到市长的任务:建设城市。球球打算建造 2n2n 座高楼。为了保证城市美观,球球做出了如下计划:

  • 球球喜欢整齐的事物。他希望高楼从左向右排成一行,编号依次为 12n1\sim 2n

  • 球球喜欢整数,他要求每座高楼的高度都是正整数。

  • 由于材料限制,高楼的高度无法超过 mm

  • 球球喜欢中间高,两边低的造型。他要求前 nn 座高楼的高度不下降,后 nn 座高楼的高度不上升。

  • 球球打算选两座编号为 x,yx,y 的高楼作为这座城市的地标。他认为只有当这两座高楼高度相等时,才会让城市变得美观。

球球把自己的想法告诉了市长。市长希望得知所有建设城市的方案数。两种方案不同,当且仅当某座高楼的高度在两个方案中不同。这个问题可难倒了球球。球球找到了你,希望你能帮他算出答案。由于答案可能很大,你只需要给出答案对 998244353998244353 取模后的结果。

输入格式

从标准输入读入数据。

仅一行四个整数 m,n,x,ym,n,x,y,变量意义见题目描述。

输出格式

输出到标准输出。

仅一行一个整数表示答案。

样例 #1

样例输入 #1

3 2 1 3

样例输出 #1

10

样例 #2

样例输入 #2

1000 1000 535 1477

样例输出 #2

295916566

提示

对于样例 11,所有的方案为:{1,1,1,1},{1,2,1,1},{1,3,1,1},{2,2,2,1},{2,2,2,2},{2,3,2,1},{2,3,2,2},{3,3,3,1},{3,3,3,2},{3,3,3,3}\{1,1,1,1\},\{1,2,1,1\},\{1,3,1,1\},\{2,2,2,1\},\{2,2,2,2\},\\\{2,3,2,1\},\{2,3,2,2\},\{3,3,3,1\},\{3,3,3,2\},\{3,3,3,3\}

对于 10%10\% 的数据,1n,m51\le n,m\le 5

对于 30%30\% 的数据,1n,m1001\le n,m\le 100

对于 60%60\% 的数据,1n,m10001\le n,m\le 1000

对于 100%100\% 的数据,1x<y2n1\le x < y \le 2n1n,m1051\le n,m \le 10^5

组合数学

#include <iostream> 
#include <cstdio>

#define int long long int

using namespace std;

const int maxn=200005;
const int mod=998244353;

int m,n,x,y;
int jc[maxn];

inline void init() {
	jc[0]=1;
	for (int i=1;i<=m+n;i++) jc[i]=jc[i-1]*i%mod;
}

inline int power(int a,int b) {
	int ans=1;
	while (b) {
		if (b&1) ans*=a,ans%=mod;
		a*=a,a%=mod;
		b>>=1;
	}
	return ans;
}

inline int inv(int k) {
	return power(k,mod-2);
}

inline int C(int m,int n) {
    return ( (jc[m] * inv(jc[n]) % mod) * inv(jc[m-n]) ) % mod;
}

signed main() {
	cin >> m >> n >> x >> y;
	if (x>y) swap(x,y);
	init();
	int ans=0;
	if (x<=n && y>n) {
		y=2*n-y+1;
		for (int i=1;i<=m;i++) {
			int valx=i+x,valy=i+y;
			int tmp=1;
			tmp*=C(valx-2,x-1),tmp%=mod;
			tmp*=C(valy-2,y-1),tmp%=mod;
			tmp*=C(n+m-valx,n-x),tmp%=mod;
			tmp*=C(n+m-valy,n-y),tmp%=mod;
			ans+=tmp,ans%=mod;
		}
		printf("%lld",ans);
		return 0;
	}
	else {
		if (x>n) x-=n,y-=n;
		for (int i=1;i<=m;i++) {
			int valx=i+x,valy=i+y;
			int tmp=1;
			tmp*=C(valx-2,x-1),tmp%=mod;
			tmp*=C(n+m-valy,n-y),tmp%=mod;
			ans+=tmp,ans%=mod;
		} 
		ans*=C(n+m-1,n),ans%=mod;
		printf("%lld",ans);
		return 0;
	}
}