本文已参与「新人创作礼」活动, 一起开启掘金创作之路。
【CCPC】2022广州站 L. Station of Fate
题目链接
题目
There are people standing in stations, forming queues.
You don't know which person is in which station, or in what order they are standing in queue, so you want to count the number of different schemes. Two schemes are considered different, if and only if there exists a station whose queue consists of different people, or has different orders.
Calculate the number of different schemes modulo 998244353.
题目大意
有 个人站在 个车站。每个车站里的所有人排成一队。
每个人可能以任意次序站在任意个车站。虽然题目没有明确给出(也许是我们英语太差),但是分析数据发现每个车站至少有一个人。
计算不同方案的数量。两种方案被认为是不同的,当且仅当存在一个车站,其队列由不同的人组成,或具有不同的顺序。
输出不同方案的数量对 998244353 取模的结果。
思路
我们先考虑每个车站里人数不同的方案。即球盒模型中的盒子互不相同,球全都一样,盒不能为空的情况。我们使用隔板法,有 个球所以有 个空,我们可以在空里选择 个位置插板使得整个段分成 份,每份里球的数量即为对应车站球的数量。
比如输入样例中有 6 个人:
人人人人人人
然后在他们中间的 5 个空隙里插 2 个板子:
人人|人人人|人
就可以把人分成 3 组。
然后再考虑在每个车站人的数量固定的、排列顺序不同的情况。因为每个站可以区分且人数固定,我们可以以车站为第一关键字以车站内的站位为第二关键字将所有人排成一列,容易发现所有人可以随便排列,将原本数量的人依次安排入车站中即可,没有重复情况。该部分答案就是 。
两部分答案相互独立,他们的积就是最终的答案。
代码
#include <bits/stdc++.h>
using namespace std;
const int p = 998244353;
using ll = long long;
ll fac[100005], inv[100005];
ll poww(ll a, ll b) {
ll res = 1;
for( ; b; b /= 2, a = (a * a) % p) if(b & 1) res = (res * a) % p; return res;
}
int main() {
fac[0] = 1;
for( int i = 1; i <= 100000; i++) {
fac[i] = (fac[i-1] * i) % p;
}
inv[100000] = poww(fac[100000], p - 2);
for( int i = 100000 - 1; i >= 0; i--) {
inv[i] = ((inv[i+1] * (i + 1))) % p;
}
int tt;
scanf("%d", &tt);
while(tt--) {
int n, m;
scanf("%d%d", &n, &m);
printf("%lld\n", fac[n] * fac[n-1] % p * inv[n-m] % p * inv[m-1] % p);
}
return 0;
}