Live2D

Solution -「Code+#4」「洛谷 P4370」组合数问题 2

Description

  Link.

  给定 n,k,求 0ban(ab) 的前 k 大。

  n106k105

Solution

  注意到 (ab)<(a+1b),所以把 (ni) 塞进堆里,取走堆顶的 (ab) 时顺手把 (a1b) 入堆就好。

  但组合数直接算会爆精度,取对数就能实现比较了。

Code

#include <cmath>
#include <queue>
#include <cstdio>

typedef std::pair<int, int> pii;

const int MAXN = 1e6, MOD = 1e9 + 7;
int n, K, nfac[MAXN + 5], ifac[MAXN + 5];
double lfac[MAXN + 5];

inline double combl ( const int n, const int m ) {
	return lfac[n] - lfac[m] - lfac[n - m];
}

inline int combn ( const int n, const int m ) {
	return 1ll * nfac[n] * ifac[m] % MOD * ifac[n - m] % MOD;
}

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;
}

struct cmp {
	inline bool operator () ( const pii a, const pii b ) {
		return combl ( a.first, a.second ) < combl ( b.first, b.second );
	}
};

std::priority_queue<pii, std::vector<pii>, cmp> heap;

int main () {
	scanf ( "%d %d", &n, &K );
	nfac[0] = nfac[1] = 1;
	for ( int i = 2; i <= n; ++ i ) {
		lfac[i] = lfac[i - 1] + log2 ( i );
		nfac[i] = 1ll * i * nfac[i - 1] % MOD;
	}
	ifac[n] = qkpow ( nfac[n], MOD - 2 );
	for ( int i = n - 1; ~ i; -- i ) ifac[i] = ( i + 1ll ) * ifac[i + 1] % MOD;
	for ( int i = 0; i <= n; ++ i ) heap.push ( { n, i } );
	int ans = 0;
	while ( K -- ) {
		pii t = heap.top (); heap.pop ();
		ans = ( ans + combn ( t.first, t.second ) ) % MOD;
		if ( t.first && t.first ^ t.second ) heap.push ( { t.first - 1, t.second } );
	}
	printf ( "%d\n", ans );
	return 0;
}
posted @   Rainybunny  阅读(126)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示