持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第16天,点击查看活动详情
[NOI Online #2 入门组] 建设城市
题目描述
球球是一位建筑师。一天,他收到市长的任务:建设城市。球球打算建造 座高楼。为了保证城市美观,球球做出了如下计划:
-
球球喜欢整齐的事物。他希望高楼从左向右排成一行,编号依次为 。
-
球球喜欢整数,他要求每座高楼的高度都是正整数。
-
由于材料限制,高楼的高度无法超过 。
-
球球喜欢中间高,两边低的造型。他要求前 座高楼的高度不下降,后 座高楼的高度不上升。
-
球球打算选两座编号为 的高楼作为这座城市的地标。他认为只有当这两座高楼高度相等时,才会让城市变得美观。
球球把自己的想法告诉了市长。市长希望得知所有建设城市的方案数。两种方案不同,当且仅当某座高楼的高度在两个方案中不同。这个问题可难倒了球球。球球找到了你,希望你能帮他算出答案。由于答案可能很大,你只需要给出答案对 取模后的结果。
输入格式
从标准输入读入数据。
仅一行四个整数 ,变量意义见题目描述。
输出格式
输出到标准输出。
仅一行一个整数表示答案。
样例 #1
样例输入 #1
3 2 1 3
样例输出 #1
10
样例 #2
样例输入 #2
1000 1000 535 1477
样例输出 #2
295916566
提示
对于样例 ,所有的方案为:。
对于 的数据,。
对于 的数据,。
对于 的数据,。
对于 的数据,, 。
组合数学
#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;
}
}