nowcoder6 C.Generation I

Generation I

题解

首先放$k$种数字的情况,有$A_n^k$中可能。

由于操作后,前面的球就无法放置,就可以第一个放置该数字的点来确定该结果的区别。相当于将$k$种放在$n$个格子里面。使用隔板法$n\choose k$。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=(a);i<(n);i++)
#define per(i,a,n) for(int i=(n-1);i>=(a);i--)
#define fi first
#define se second
typedef pair <int,int> pII;
typedef long long ll;
const int INF = 0x3f3f3f3f;
//head
const ll mod = 998244353;
int T;
const int maxn = 1e6 + 10;
ll cur,p[maxn],q[maxn],inv[maxn];
ll n,m;
ll C(ll n,ll k){
return p[n]*q[k]%mod*q[n-k]%mod;
}
ll c(ll n,ll k){
if(n<maxn) return C(n,k);
if(!k) return 1;
return cur = cur*inv[k]%mod*((n-k+1)%mod)%mod;
}
void init(){
p[0] = p[1] = q[0] = q[1] = inv[0] = inv[1] = 1;
for(ll i = 2;i<maxn;i++){
inv[i] = (mod-mod/i)*inv[mod%i]%mod;
q[i] = q[i-1]*inv[i]%mod;
p[i] = p[i-1] * i % mod;
}
}
int main(){
#ifdef LOCAL
freopen("j.in","r",stdin);
#endif
init();
scanf("%d",&T);
rep(test_case,1,T+1){
scanf("%lld%lld",&n,&m);
ll len = min(n,m);
ll ans = 0;
cur = 1;
for(ll i = 1;i<=len;i++){
ans = (ans + (c(m,i)*p[i]%mod)*c(n-1,i-1)%mod)%mod;
}
printf("Case #%d: %lld\n",test_case,ans);
}
return 0;
}