关于特殊组合数的计算
  • 板块学术版
  • 楼主cancan123456
  • 当前回复6
  • 已保存回复6
  • 发布时间2022/2/8 22:36
  • 上次更新2023/10/28 09:21:39
查看原帖
关于特殊组合数的计算
448887
cancan123456楼主2022/2/8 22:36

RT,在 P6078 这道题里,需要快速计算 (nm)\binom{n}{m},而其中 mm 最大只可能是 10,所以我就想用 (nm)=n(n1)(nm+1)m!\binom{n}{m}=\dfrac{n(n-1)\cdots(n-m+1)}{m!} 然后上下约分来计算,但是为什么只有 51 分呢?

代码:

#include <cstdio>
using namespace std;
typedef long long ll;
const ll mod = 2004;
ll n;
ll m[10];
ll ans;
void fix(ll & a) {
	a = (a % mod + mod) % mod;
}
ll fm[10];
ll C(ll n, ll m) {
	// m 一定是题目中给的 n 
	// 考虑约分计算 
	for (ll i = 0; i < m; i++) {
		fm[i] = n - i;
	}
	for (ll i = m; i >= 1; i--) {
		for (ll j = 0; j < m; j++) {
			if (fm[j] % i == 0) {
				fm[j] /= i;
				break;
			}
		}
	}
	ll ans = 1;
	for (int i = 0; i < m; i++) {
		ans = ans * fm[i] % mod;
	}
	return ans;
}
void dfs(ll i, ll v, ll c, ll lim) {
	if (c > lim) {
		return;
	} else if (i == n) {
		ans = ans + v * C(n + lim - c, n);
		fix(ans);
	} else {
		dfs(i + 1, v, c, lim);
		dfs(i + 1, -v, c + m[i] + 1, lim);
	}
}
ll solve(ll k) {
	ans = 0;
	dfs(0, 1, 0, k);
	return ans;
}
int main() {
	ll a, b;
	scanf("%lld %lld %lld", &n, &a, &b);
	for (ll i = 0; i < n; i++) {
		scanf("%lld", m + i);
	}
	ll ans = solve(b) - solve(a - 1);
	fix(ans);
	printf("%lld", ans);
	return 0;
}
2022/2/8 22:36
加载中...