题目要求当\(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. protobuf总结

    1.protobuf是什么? protobuf(protocol buffers)是一种语言中立,平台无关,可扩展的序列化数据的格式,可以用于通信协议,数据存储等. protobuf 相比于xml,j ...

  2. Mysql基础知识一

    1.数据库的定义 数据:描述事物符号记录.(包括数字.文字.图形.图像.声音.档案记录等)以记录形式统一的格式进行存储. 广义上的数据:出现在计算机内部的一切二进制数据流都为数据 狭义上的数据:只是数 ...

  3. 让图片适合在静态文本控件窗口大小 MFC

    1.加入 IDC_STATIC1 静态文本控件. 2.为文本控件添加 STATIC 型变量 3.在OnInitDialog函数中添加以下代码 //设置该静态控件为显示位图的 m_bitmap.Modi ...

  4. 使用原生js实现选项卡功能实例教程

    选项卡是前端常见的基本功能,它是用多个标签页来区分不同内容,通过选择标签快速切换内容.学习本教程之前,读者需要具备html和css技能,同时需要有简单的javascript基础. 先来完成html部分 ...

  5. 你知道python入门,是学到什么程度才算是吗?

    1.入门的标准是什么? 这是很多初学者都关注的问题,但又是一个很难回答的问题,问题的核心是采取什么标准来衡量一个人是否已经入门. 以知识量的多少来衡量是不是可行呢?有些人走马观花一般学了很多pytho ...

  6. 解决vue element table行列不齐问题

    全局加入如下样式即可(app.vue): body .el-table th.gutter{ display: table-cell!important; }

  7. v&n赛 内存取证题解(已更新)

    题目是一个raw的镜像文件 用volatility搜索一下进程 有正常的notepad,msprint,还有dumpit和truecrypt volatility -f mem.raw --profi ...

  8. 尝试用Vue.js开发网页小游戏的过程

    准备 首先去官方下载并安装VSCODE,下载地址 https://code.visualstudio.com/.安装后打开会发现是英文版的,需要去安装插件来汉化.具体是在扩展插件搜索chinese,选 ...

  9. 认证与授权】Spring Security系列之认证流程解析

    上面我们一起开始了Spring Security的初体验,并通过简单的配置甚至零配置就可以完成一个简单的认证流程.可能我们都有很大的疑惑,这中间到底发生了什么,为什么简单的配置就可以完成一个认证流程啊 ...

  10. springboot+dubbo简单分布式RPC调用demo

    使用springboot+dubbo搭建RPC入门案例 本文背景简述: 最近在学习公司的一套RPC框架,初步接触的时候感觉挺复杂的.但是知道其原理肯定是和dubbo很相似的,毕竟都是RPC框架嘛,只是 ...