Live2D

Solution -「ARC 110D」Binomial Coefficient is Fun

\(\mathcal{Description}\)

  Link.

  给定非负整数序列 \(\{a_n\}\),设 \(\{b_n\}\) 是一个非负整数序列且 \(\sum_{i=1}^nb_i\le m\),求

\[\sum_{\{b_n\}}\prod_{i=1}^n\binom{b_i}{a_i}\bmod(10^9+7) \]

  \(n,a_i\le2\times10^3\)

\(\mathcal{Solution}\)

  鉴于这是 ARC D,可以直观感受到是一个代码不长的组合意义题。(

  考虑一个 \(\prod_{i=1}^n\binom{b_i}{a_i}\) 的意义:

\(m\) 个球排成一行,将其分成 \(n+1\) 段,第 \(i~(i\le n)\) 段长度 \(b_i\),再从这些段内选 \(a_i\) 个球。

  那么对其求和,意义即为:

\(m\) 个球排成一行,将其任意分成 \(n+1\) 段,再从前 \(n\) 段内每段选 \(a_i\) 个球。

  把“分段”当成球,所以:

\(m+n\) 个球排成一行,先选 \(a_1\) 个球,再选 \(1\) 个球,接着选 \(a_2\) 个球,再选 \(1\) 个球……

  进一步:

\(m+n\) 个球排成一行,选 \(n+\sum_{i=1}^na_i\) 个球。

  故答案为 \(\binom{n+m}{n+\sum_{i=1}^na_i}\)。复杂度 \(\mathcal O(\sum_{i=1}^na_i)\)

\(\mathcal{Code}\)

/* Clearink */

#include <cstdio>

#define rep( i, l, r ) for ( int i = l, rpbound##i = r; i <= rpbound##i; ++i )
#define per( i, r, l ) for ( int i = r, rpbound##i = l; i >= rpbound##i; --i )

const int MOD = 1e9 + 7, MAXN = 2e3;
int n, m, fac[MAXN + 5], inv[MAXN * MAXN + 5];

inline int mul ( const long long a, const int b ) { return a * b % MOD; }

inline void init ( const int n ) {
	inv[1] = 1;
	rep ( i, 2, n ) inv[i] = mul ( inv[MOD % i], MOD - MOD / i );
}

inline int comb ( const int n, const int m ) {
	if ( n < m ) return 0;
	int ret = 1;
	for ( int i = 1; i <= m; ++i ) ret = mul ( ret, mul ( n - i + 1, inv[i] ) );
	return ret;
}

int main () {
	scanf ( "%d %d", &n, &m );
	int s = 0;
	for ( int i = 1, a; i <= n; ++i ) {
		scanf ( "%d", &a );
		s += a;
	}
	init ( s + n );
	printf ( "%d\n", comb ( n + m, s + n ) );
	return 0;
}

posted @ 2021-01-18 15:57  Rainybunny  阅读(168)  评论(3编辑  收藏  举报