Live2D

Solution -「ARC 110D」Binomial Coefficient is Fun

Description

  Link.

  给定非负整数序列 {an},设 {bn} 是一个非负整数序列且 i=1nbim,求

{bn}i=1n(biai)mod(109+7)

  n,ai2×103

Solution

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

  考虑一个 i=1n(biai) 的意义:

m 个球排成一行,将其分成 n+1 段,第 i (in) 段长度 bi,再从这些段内选 ai 个球。

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

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

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

m+n 个球排成一行,先选 a1 个球,再选 1 个球,接着选 a2 个球,再选 1 个球……

  进一步:

m+n 个球排成一行,选 n+i=1nai 个球。

  故答案为 (n+mn+i=1nai)。复杂度 O(i=1nai)

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 @   Rainybunny  阅读(179)  评论(3编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示