发现
C
(
a
,
b
)
<
C
(
a
,
b
+
1
)
C(a,b) < C(a,b+1)
C(a,b)<C(a,b+1)
那么就是有n个递增队列
q
i
q_i
qi,满足
q
i
j
=
C
(
i
,
j
)
q_{ij} = C(i,j)
qij=C(i,j)
每次找出队头最大的,然后把队头删去,重复k次。
比大小可以取对数
#include<bits/stdc++.h>
#define maxn 1000006
#define mod 1000000007
#define eps 1e-8
#define LL long long
using namespace std;
LL C[505][505];
int fac[maxn]={1,1},inv[maxn]={1,1},invf[maxn]={1,1},ans;
int num[3000005],cnt,c[3000005];
double lgv[maxn],lgf[maxn],lgn[maxn];
inline bool cmp(const int &u,const int &v){ return lgn[u] > lgn[v] + eps; }
int main()
{
C[0][0] = 1;
for(int i=1;i<505;i++)
{
C[i][0] = 1;
for(int j=1;j<505;j++) C[i][j] = C[i-1][j-1] + C[i-1][j];
}
for(int i=1;i<505;i++) lgv[i] = log(i) , lgf[i] = lgv[i] + lgf[i-1];
int n,k;
scanf("%d%d",&n,&k);
if(n <= 10)
{
priority_queue<LL>q;
for(int i=0;i<=n;i++)
for(int j=0;j<=i;j++)
q.push(C[i][j]);
for(;k;k--)
ans = (ans + q.top()) % mod , q.pop();
printf("%d\n",(ans+mod)%mod);
}
else
{
for(int i=2;i<=n;i++)
fac[i] = 1ll * fac[i-1] * i % mod,
inv[i] = 1ll * (mod - mod / i) * inv[mod % i] % mod,
invf[i] = 1ll * invf[i-1] * inv[i] % mod;
if(k==1) printf("%lld\n",1ll * fac[n] * invf[n/2] % mod * invf[n-(n/2)] % mod);
else
{
for(int i=0;i<=n;i++)
for(int j=0;j<=i;j++)
num[++cnt] = C[i][j] , lgn[cnt] = lgf[i] - lgf[j] - lgf[i-j] , c[cnt] = cnt;
sort(c+1,c+1+cnt,cmp);
for(int i=1;i<=k;i++)
ans = (ans + num[c[i]]) % mod;
printf("%d\n",(ans+mod)%mod);
}
}
}