同一道题:小狗狗也AK了!
题面
两个长度为 K K K 的正整数数列 a a a 和 b b b,满足 ∑ i = 1 K a i = N , ∑ i = 1 K b i = M \sum_{i=1}^Ka_i=N~,~\sum_{i=1}^Kb_i=M ∑i=1Kai=N , ∑i=1Kbi=M,对于这两个数列,定义权值为 P = ∏ i = 1 K min ( a i , b i ) P=\prod_{i=1}^K\min(a_i,b_i) P=∏i=1Kmin(ai,bi) 。求所有可能的数列的权值之和。答案对 998244353 998244353 998244353 取模。
T T T 组数据,每组数据给出 N , M , K N,M,K N,M,K 。
T ≤ 100 , 1 ≤ N , M , K ≤ 5 × 1 0 5 , K ≤ min ( N , M ) T\leq 100,1\leq N,M,K\leq5\times10^5,K\leq\min(N,M) T≤100,1≤N,M,K≤5×105,K≤min(N,M) 。
题解
做一个转换:『权值』即为长度为 K K K 的正整数数列 c c c 的数量,满足 ∀ i ∈ [ 1 , K ] , c i ≤ a i , c i ≤ b i \forall i\in[1,K]~,~c_i\leq a_i,c_i\leq b_i ∀i∈[1,K] , ci≤ai,ci≤bi 。
我们反向求,先求 c c c 的数量,再求与之对应的 ( a , b ) (a,b) (a,b) 方案数。
假设我们确定了 c c c,我们可以令 a i = a i − c i , b i = b i − c i a_i=a_i-c_i~,~b_i=b_i-c_i ai=ai−ci , bi=bi−ci ,然后 a , b a,b a,b 就成了长度为 K、总和分别为 N − ∑ c i N-\sum c_i N−∑ci、 M − ∑ c i M-\sum c_i M−∑ci 的自然数数列 。
因此,枚举 x = ∑ c i x=\sum c_i x=∑ci ,对应的 c c c 的数量为 C ( x − 1 , K − 1 ) C(x-1,K-1) C(x−1,K−1) , a a a 的数量为 C ( M − x − 1 + K , K − 1 ) C(M-x-1+K,K-1) C(M−x−1+K,K−1), b b b 的数量为 C ( M − x − 1 + K , K − 1 ) C(M-x-1+K,K-1) C(M−x−1+K,K−1) 。
于是,答案为
∑
x
=
K
min
(
N
,
M
)
C
(
x
−
1
,
K
−
1
)
⋅
C
(
M
−
x
−
1
+
K
,
K
−
1
)
⋅
C
(
M
−
x
−
1
+
K
,
K
−
1
)
\sum_{x=K}^{\min(N,M)} C(x-1,K-1)\cdot C(M-x-1+K,K-1)\cdot C(M-x-1+K,K-1)
x=K∑min(N,M)C(x−1,K−1)⋅C(M−x−1+K,K−1)⋅C(M−x−1+K,K−1)
CODE
很快啊
#include<map>
#include<set>
#include<stack>
#include<queue>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 500005
#define LL long long
#define DB double
#define ENDL putchar('\n')
#define lowbit(x) (-(x):(x))
#define SI(x) set<x>::iterator
#define FI first
#define SE second
LL read() {
LL f=1,x=0;char s = getchar();
while(s < '0' || s > '9') {if(s=='-')f = -f;s = getchar();}
while(s >= '0' && s <= '9') {x=x*10+(s-'0');s = getchar();}
return f * x;
}
void putpos(LL x) {
if(!x) return ;
putpos(x/10); putchar('0'+(x%10));
}
void putnum(LL x) {
if(!x) {putchar('0');return ;}
if(x < 0) putchar('-'),x = -x;
putpos(x);
}
void AIput(LL x,char c) {putnum(x);putchar(c);}
const int MOD = 998244353;
int n,m,s,o,k;
int fac[MAXN<<1],inv[MAXN<<1],invf[MAXN<<1];
int C(int n,int m) {
if(m < 0 || m > n) return 0;
return fac[n] *1ll* invf[n-m] % MOD * invf[m] % MOD;
}
int main() {
freopen("easy.in","r",stdin);
freopen("easy.out","w",stdout);
fac[0]=fac[1]=inv[0]=inv[1]=invf[0]=invf[1]=1;
for(int i = 2;i <= MAXN*2-5;i ++) {
fac[i] = fac[i-1] *1ll* i % MOD;
inv[i] = (MOD - inv[MOD%i]) *1ll* (MOD/i) % MOD;
invf[i] = invf[i-1] *1ll* inv[i] % MOD;
}
int T = read();
while(T --) {
n = read();m = read();k = read();
if(n > m) swap(n,m);
int ans = 0;
for(int i = k;i <= n;i ++) {
int bs = C(i-1,k-1);
int ct = C(n-i-1+k,k-1) *1ll* C(m-i-1+k,k-1) % MOD;
(ans += bs*1ll*ct % MOD) %= MOD;
}
AIput(ans,'\n');
}
return 0;
}