题目要求当\(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. 如何关闭php的所有错误提示

    在调试PHP 应用程序时,应当知道两个配置变量.下面是这两个变量及其默认值:display_errors = Offerror_reporting = E_ALL E_ALL能从不良编码实践到无害提示 ...

  2. PHP中嵌入正则表达式常用的函数

    PHP中嵌入正则表达式常用的函数有四个: 1.preg_match() :preg_match() 函数用于进行正则表达式匹配,成功返回 1 ,否则返回 0 . 语法:int preg_match( ...

  3. 10.1 io流--ASCII码表

    day2.8中提到 /* * +: * 做加法运算 * * 字符参与加法运算,其实是拿字符在计算机中存储的数据值来参与运算的 * 'A' 65(B 66...) * 'a' 97(b 98...) * ...

  4. not found 什么时候触发

    eq: BEGIN        DECLARE EXIT HANDLER FOR NOT FOUND SET o_state = 999;         select count(1) into ...

  5. Win32 Disk Imager刻录过的U盘恢复容量的方法

    近日遇到一个问题,使用Win32 Disk Imager刻录过的U盘,想恢复使用,但无法正常使用. 按WIN+R键调出Win10运行框,输入diskmgmt.msc,打开磁盘管理工具. 看到U盘的状况 ...

  6. 我是如何一步步的在并行编程中将lock锁次数降到最低实现无锁编程

    在并行编程中,经常会遇到多线程间操作共享集合的问题,很多时候大家都很难逃避这个问题做到一种无锁编程状态,你也知道一旦给共享集合套上lock之后,并发和伸缩能力往往会造成很大影响,这篇就来谈谈如何尽可能 ...

  7. Linux学习笔记(二)文件操作命令

    文件操作命令 touch stat cat more less head tail ln touch 英文原意: change file timestamps 功能: 修改文件的时间戳 语法: tou ...

  8. testNG 下载安装

    testNG的安装方法: 一.在线安装 打开eclipse 选择-->help-->Install New Software选项 ,弹出下面的弹框,Work with框输入 http:// ...

  9. Jmeter--Plugins Manager安装及常用的插件介绍

    jmeter 客户端 内置的插件管理工具Plugins Manager 1.下载地址:https://jmeter-plugins.org/install/Install/ 2.将下载的文件拷贝的你的 ...

  10. RocketMQ存储机制与确认重传机制

    引子 消息队列之前就听说过,但一直没有学习和接触,直到最近的工作流引擎项目用到,需要了解学习一下.本文主要从一个初学者的角度针对RocketMQ的存储机制和确认重传机制做一个浅显的总结. 存储机制 我 ...