题目要求当\(0\leq a\leq b\leq n\)时,\(k\)个\(\tbinom{b}{a}\)的和的最大值

观察杨辉三角形,可以发现,最大的\(\tbinom{b}{a}\),为\(\tbinom{n}{\frac{n}{2}}\)

还可以知道,除了当前最大的组合数以外,可能最大的,是它周围的四个

即如果当前确定的最大组合数为\(\tbinom{n}{m}\),则接下来有可能成为最大的数是:\(\tbinom{n}{m-1},\tbinom{n}{m+1},\tbinom{n-1}{m-1},\tbinom{n-1}{m}\)

可以写一个杨辉三角理解一下

然后可以用一个优先队列维护,每次取出当前的最大值

那么如何比较两个组合数的大小?写高精算出来(bushi

用一个神奇的方法:取\(\log\)

由\(\log ab=\log a+\log b,\log\frac{a}{b}=\log a-\log b\)

则可以先预处理出\(\log x!,0\leq x\leq n\),然后再算组合数\(\tbinom{n}{m}=\log n!-\log m!-\log (n-m)!\)

然后在堆中比较\(\log\)的大小

然后我愉快的把堆写炸了

算组合数就是预处理阶乘和阶乘逆元就行了

一定要记得判断当前最大的组合数周围的那四个数是否存在,具体见代码

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<iomanip>
#include<cstring>
#include<map>
#define reg register
#define EN std::puts("")
#define LL long long
inline int read(){
int x=0,y=1;
char c=std::getchar();
while(c<'0'||c>'9'){if(c=='-') y=0;c=std::getchar();}
while(c>='0'&&c<='9'){x=x*10+(c^48);c=std::getchar();}
return y?x:-x;
}
int n,k;
const LL mod=1e9+7;
struct data{
int n,m;
double Log;
}dui[500006];
int size;
LL fac[1000006],inv[1000006];
double Log[1000006];
std::map<std::pair<int,int>,bool>map;
inline void push(data x){
map[std::make_pair(x.n,x.m)]=1;
dui[++size]=x;
reg int i=size,fa;
while(i>1){
fa=i>>1;
if(dui[fa].Log>dui[i].Log) break;
std::swap(dui[fa],dui[i]);i=fa;
}
}
inline data pop(){
data ret=dui[1];dui[1]=dui[size--];
reg int i=1,ls,rs;
while((ls=i<<1)<=size){
rs=ls|1;
if(rs<=size&&dui[rs].Log>dui[ls].Log) ls=rs;
if(dui[i].Log>dui[ls].Log) break;
std::swap(dui[i],dui[ls]);i=ls;
}
return ret;
}
inline LL power(LL a,LL b){
LL ret=1;
while(b){
if(b&1) ret=(ret*a)%mod;
a=(a*a)%mod;b>>=1;
}
return ret;
}
inline void pre(){
fac[0]=inv[0]=1;
for(reg int i=1;i<=n;i++) fac[i]=(fac[i-1]*i)%mod;
inv[n]=power(fac[n],mod-2);
for(reg int i=n-1;i;i--) inv[i]=(inv[i+1]*(i+1))%mod;
for(reg int i=1;i<=n;i++) Log[i]=log(i)+Log[i-1];
}
inline double getLog(int nn,int mm){
return Log[nn]-Log[mm]-Log[nn-mm];
}
int main(){
n=read();k=read();
pre();
push((data){n,n/2,getLog(n,n/2)});
reg data now;
reg LL ans=0;
std::pair<int,int>tmp;
reg int nn,mm;
while(k--){
now=pop();
nn=now.n;mm=now.m;
ans+=((fac[nn]*inv[mm])%mod*inv[nn-mm])%mod;
ans%=mod;
// std::printf("%d %d %d\n",ans,nn,mm);
if(mm-1>=0){
tmp=std::make_pair(nn,mm-1);
if(!map[tmp])
push((data){nn,mm-1,getLog(nn,mm-1)});
}
if(mm+1<=nn){
tmp=std::make_pair(nn,mm+1);
if(!map[tmp])
push((data){nn,mm+1,getLog(nn,mm+1)});
}
if(mm-1>=0&&nn-1>=0){
tmp=std::make_pair(nn-1,mm-1);
if(!map[tmp])
push((data){nn-1,mm-1,getLog(nn-1,mm-1)});
}
if(nn-1>=mm){
tmp=std::make_pair(nn-1,mm);
if(!map[tmp])
push((data){nn-1,mm,getLog(nn-1,mm)});
}
}
std::printf("%lld",ans);
return 0;
}

P4370 [Code+#4]组合数问题2的更多相关文章

  1. POJ 1850 Code(组合数)

    http://poj.org/problem?id=1850 题意 :给定字符串,系统是用字符串组成的,字符串是按字典序排的.编码系统有三条规则,1这些的单词的长度是由小到大的,2相同长度的按字母在字 ...

  2. 清北学堂Day3

    卷积公式(Dirichlet卷积) 这个式子看上去就很变态,那么他是什么意思呢: 就是说 函数f(x)和g(x)对于n的卷积等于n的每一个因子d在f(x)上的值乘上d/n在g(x)上的值的和 例:设g ...

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

    \(\mathcal{Description}\)   Link.   给定 \(n,k\),求 \(0\le b\le a\le n\) 的 \(\binom{a}{b}\) 的前 \(k\) 大. ...

  4. poj Code(组合数)

    Code Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 9918   Accepted: 4749 Description ...

  5. Code (组合数)

    Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 7184   Accepted: 3353 Description Trans ...

  6. POJ 3904 JZYZOJ 1202 Sky Code 莫比乌斯反演 组合数

    http://poj.org/problem?id=3904   题意:给一些数,求在这些数中找出四个数互质的方案数.   莫比乌斯反演的式子有两种形式http://blog.csdn.net/out ...

  7. LCM性质 + 组合数 - HDU 5407 CRB and Candies

    CRB and Candies Problem's Link Mean: 给定一个数n,求LCM(C(n,0),C(n,1),C(n,2)...C(n,n))的值,(n<=1e6). analy ...

  8. C++单元测试 之 gtest -- 组合数计算.

    本文将介绍如何使用gtest进行单元测试. gtest是google单元测试框架.使用非常方便. 首先,下载gtest (有些google项目包含gtest,如 protobuf),复制目录即可使用. ...

  9. 【BZOJ-4591】超能粒子炮·改 数论 + 组合数 + Lucas定理

    4591: [Shoi2015]超能粒子炮·改 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 95  Solved: 33[Submit][Statu ...

随机推荐

  1. Google GMS介绍

    Google GMS介绍GMS全称为GoogleMobile Service.GMS目前提供有Search.Search by Voice.Gmail.Contact Sync.Calendar Sy ...

  2. git log查看某文件的修改历史

    1. git log filename 可以看到fileName相关的commit记录 2. git log -p filename可以显示每次提交的diff 3. 只看某次提交中的某个文件变化,可以 ...

  3. 装机摸鱼日志--ubuntu16.04安装网易云音乐客户端

    之前装的网易云音乐不指定啥原因不能用了,所以打算重新装一个,但是进官网只有deepin15和ubuntu18.04版本的安装包.然后我装了一下18.04的安装包,但是没有成功.甚至因为更换glibc差 ...

  4. Linux-Deepin 下开启SSH远程登陆

    #### 关于deepin系统安装ssh后,root超级用户登录报错的完美解决方案! 最近刚刚接触到deepin,觉得,wow,除了mac,还有这么好看的非win系统,而且第测出那个Linux,宽容度 ...

  5. [转载]深度理解Session

    什么是session session的官方定义是:Session:在计算机中,尤其是在网络应用中,称为“会话控制”.Session 对象存储特定用户会话所需的属性及配置信息. 说白了session就是 ...

  6. sql注入原理+mysql相关知识点

    什么是SQL注入 sql就是经常说的数据库,而sql注入就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令.SQL注入是比较常见的网络攻击 ...

  7. Spark SQL源码解析(三)Analysis阶段分析

    Spark SQL原理解析前言: Spark SQL源码剖析(一)SQL解析框架Catalyst流程概述 Spark SQL源码解析(二)Antlr4解析Sql并生成树 Analysis阶段概述 首先 ...

  8. 当git上只做文件大小写重命名的修改时,如何躲坑

    一. 提交时 假设修改ABC.java为Abc.java. 1.1 如果使用git命令进行仅涉及大小写的重命名 1.1.1 设置git库为大小写敏感(不建议) $ git config core.ig ...

  9. 2019-2020-1 20199329《Linux内核原理与分析》第十一周作业

    <Linux内核原理与分析>第十一周作业 一.本周内容概述: 学习linux安全防护方面的知识 完成实验楼上的<ShellShock 攻击实验> 二.本周学习内容: 1.学习& ...

  10. QFileDialog::getOpenFileName() hangs

    https://forum.qt.io/topic/49209/qfiledialog-getopenfilename-hangs-in-windows-when-using-the-native-d ...