Solution -「LOCAL」「cov. 牛客多校 2020 第五场 C」Easy

(mathcal{Description})

  Link.(完全一致)

  给定 (n,m,k),对于两个长度为 (k) 的满足 (left(sum_{i=0}^ka_i=n ight)landleft(sum_{i=1}^kb_i=m ight)) 的正整数序列对 ({a_k},{b_k}),其权值为 (prod_{i=1}^kmin{a_i,b_i})。求所有序列对的权值之和,对 (998244353) 取模。

  (n,m,kle10^6)

(mathcal{Solution})

  我们尝试寻找 ([x^ay^b]G(x,y)=min{a,b}~(a,b>0)) 中的 ( ext{OGF}) (G(x,y))。由于 (x^ay^b=(xy)^{min{a,b}}x^{a-min{a,b}}y^{b-min{a,b}}),相当于要数出 (x^ay^b)(xy) 的个数。枚举 (xy) 的指数,就有:

[min{a,b}x^ay^b=sum_{i=0}^{min{a,b}-1}(xy)^ix^{a-i}y^{b-i} ]

  构造一下,有:

[G(x,y)=left(sum_{i=1}^{+infty}x^i ight)left(sum_{i=1}^{+infty}y^i ight)left(sum_{i=0}^{+infty}x^iy^i ight) ]

  答案即为:

[[x^ny^m]G^k(x,y) ]

  枚举 (xy) 的指数,三项的贡献均可以用隔板法算出来,故单组 (mathcal O(n)) 得解。

(mathcal{Code})

#include <cstdio>

const int MAXN = 2e6, MOD = 998244353;
int n, m, K, fac[MAXN + 5], ifac[MAXN + 5];

inline int qkpow ( int a, int b, const int p = MOD ) {
	int ret = 1;
	for ( ; b; a = 1ll * a * a % p, b >>= 1 ) ret = 1ll * ret * ( b & 1 ? a : 1 ) % p;
	return ret;
}

inline void init () {
	fac[0] = 1;
	for ( int i = 1; i <= MAXN; ++ i ) fac[i] = 1ll * i * fac[i - 1] % MOD;
	ifac[MAXN] = qkpow ( fac[MAXN], MOD - 2 );
	for ( int i = MAXN - 1; ~i; -- i ) ifac[i] = ( i + 1ll ) * ifac[i + 1]  % MOD;
}

inline int comb ( const int n, const int m ) {
	return n < m ? 0 : 1ll * fac[n] * ifac[m] % MOD * ifac[n - m] % MOD;
}

int main () {
//	freopen ( "easy.in", "r", stdin );
//	freopen ( "easy.out", "w", stdout );
	init (); int T;
	for ( scanf ( "%d", &T ); T --; ) {
		scanf ( "%d %d %d", &n, &m, &K );
		int ans = 0, up = n < m ? n : m;
		for ( int i = 0; i <= up; ++ i ) {
			ans = ( ans + 1ll * comb ( i + K - 1, K - 1 ) * comb ( n - i - 1, K - 1 ) % MOD
				* comb ( m - i - 1, K - 1 ) ) % MOD;
		}
		printf ( "%d
", ans );
	}
	return 0;
}

(mathcal{Details})

  直接丢构造富有数学的美感。

原文地址:https://www.cnblogs.com/rainybunny/p/13614274.html