【P4370 [Code+#4]组合数问题2】题解
给一个小题目
来源于钟神的讲解
【description】
如何比较
【solution1】:
我们可以暴力求解计算,显然是不能取模的,这就很被动,因为我们根本存不了那么大,那么我们就可以考虑一下别的方法。
取对数 : 这么大,我们取个对数就能够比较了,
来到正片
【P4370 [Code+#4]组合数问题2】
【solution2】 :
这道题的做法,其实很显然,就是有一个地方很坑,就是
- 流程:
- 我们先
n 个玩意逐个压进堆里去。 - 枚举
k 次,以此从堆里找大的用
【Code】
/*
By : Zmonarch
知识点:
*/
#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <queue>
#define int long long
#define qwq register
#define inf 2147483647
const int kmaxn = 1e6 + 10 ;
const int kmod = 1e9 + 7 ;
inline int read() {
int x = 0 , f = 1 ; char ch = getchar() ;
while(!isdigit(ch)) {if(ch == '-') f = - 1 ; ch = getchar() ;}
while( isdigit(ch)) {x = x * 10 + ch - '0' ; ch = getchar() ;}
return x * f ;
}
struct Node{
int n , m ;
double val ;
bool operator < (const Node &b) const {return val < b.val ;}
};
std::priority_queue<Node> q ;
int n , k , ret ;
int jc[kmaxn] , inv[kmaxn] ;
double lg[kmaxn] ;
void init(int n) {
inv[1] = inv[0] = jc[0] = 1 ;
for(qwq int i = 1 ; i <= n ; i++) jc[i] = jc[i - 1] * i % kmod ;
for(qwq int i = 1 ; i <= n ; i++) lg[i] = lg[i - 1] + log(i) ;
for(qwq int i = 2 ; i <= n ; i++) inv[i] = ( - kmod / i + kmod) * inv[kmod % i] % kmod ;
for(qwq int i = 1 ; i <= n ; i++) inv[i] = inv[i - 1] * inv[i] % kmod ; // 我们要的是阶乘的逆元
}
signed main() {
init(kmaxn); n = read() , k = read() ;
for(qwq int i = 0 ; i <= n ; i++)
{
Node u ;
u.n = n ; u.m = i ; u.val = lg[n] - lg[i] - lg[n - i] ;
q.push(u) ;
}
while(k--)
{
Node u = q.top() ; q.pop() ;
ret = (ret + jc[u.n] * inv[u.m] % kmod * inv[u.n - u.m]) % kmod ;
//printf("%lld %lld %lf\n" , u.n , u.m , u.val) ;
Node nxt ;
nxt.n = u.n - 1 ; nxt.m = u.m ; nxt.val = (lg[nxt.n] - lg[nxt.m] - lg[nxt.n - nxt.m]) ;
q.push(nxt) ;
}
printf("%lld\n" , ret) ;
return 0 ;
}