P4370 [Code+#4]组合数问题2
题目要求当\(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的更多相关文章
- POJ 1850 Code(组合数)
http://poj.org/problem?id=1850 题意 :给定字符串,系统是用字符串组成的,字符串是按字典序排的.编码系统有三条规则,1这些的单词的长度是由小到大的,2相同长度的按字母在字 ...
- 清北学堂Day3
卷积公式(Dirichlet卷积) 这个式子看上去就很变态,那么他是什么意思呢: 就是说 函数f(x)和g(x)对于n的卷积等于n的每一个因子d在f(x)上的值乘上d/n在g(x)上的值的和 例:设g ...
- Solution -「Code+#4」「洛谷 P4370」组合数问题 2
\(\mathcal{Description}\) Link. 给定 \(n,k\),求 \(0\le b\le a\le n\) 的 \(\binom{a}{b}\) 的前 \(k\) 大. ...
- poj Code(组合数)
Code Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 9918 Accepted: 4749 Description ...
- Code (组合数)
Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 7184 Accepted: 3353 Description Trans ...
- POJ 3904 JZYZOJ 1202 Sky Code 莫比乌斯反演 组合数
http://poj.org/problem?id=3904 题意:给一些数,求在这些数中找出四个数互质的方案数. 莫比乌斯反演的式子有两种形式http://blog.csdn.net/out ...
- 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 ...
- C++单元测试 之 gtest -- 组合数计算.
本文将介绍如何使用gtest进行单元测试. gtest是google单元测试框架.使用非常方便. 首先,下载gtest (有些google项目包含gtest,如 protobuf),复制目录即可使用. ...
- 【BZOJ-4591】超能粒子炮·改 数论 + 组合数 + Lucas定理
4591: [Shoi2015]超能粒子炮·改 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 95 Solved: 33[Submit][Statu ...
随机推荐
- leetcode c++做题思路和题解(4)——队列的例题和总结
队列的例题和总结 0. 目录 栈实现队列 队列实现栈 滑动窗口最大值 1. 栈实现队列 FIFO和FILO,相当于+-号,互转都是利用"负负得正"的原理. 官方解答中第二种思路很6 ...
- cmd批处理转义字符%的详细解释
cmd批处理转义字符%的详细解释 在命令行中使用for时不需要双%,这源于命令解释器对命令行与批处理的处理方式不同. 1.%是个ESCAPE字符,通常将之译为转义字符,但也有更形象的译名脱逸字符.逃逸 ...
- fork()系统调用的理解
系统调用fork()用于创建一个新进程.我们可以通过下面的代码来理解,最好是能自己敲一遍运行验证. #include<stdio.h> #include<stdlib.h> ...
- AJ学IOS(50)多线程网络之GCD简单介绍(任务,队列)
AJ分享,必须精品 GCD简单介绍 1.什么是GCD? 全称是Grand Central Dispatch,可译为“牛逼的中枢调度器” 纯C语言,提供了非常多强大的函数 2.GCD的优势 GCD是苹果 ...
- 动态规划_基础_最长公共子序列_多种方法_递归/dp
D: 魔法少女资格面试 题目描述 众所周知,魔法少女是一个低危高薪职业.随着近年来报考魔法少女的孩子们越来越多,魔法少女行业已经出现饱和现象!为了缓和魔法少女界的就业压力,魔法少女考核员丁丁妹决定增加 ...
- 原创hadoop2.6.4 namenode HA+Federation集群高可用部署
今天下午刚刚搭建了一个高可用hadoop集群,整理如下,希望大家能够喜欢. namenode HA:得有两个节点,构成一个namenode HA集群 namenode Federation:可以有 ...
- Volatile的应用DCL单例模式(四)
Volatile的应用 单例模式DCL代码 首先回顾一下,单线程下的单例模式代码 /** * 单例模式 * * @author xiaocheng * @date 2020/4/22 9:19 */ ...
- OkHttp 优雅封装 OkHttps 之 回调线程魔变
第一篇:OkHttp 优雅封装 HttpUtils 之 气海雪山初探 第二篇:OkHttp 优雅封装 HttpUtils 之 上传下载解密 简介 HttpUtils 从 v2.3.0 之后便重命名了, ...
- 实现一个简单的基于动态代理的 AOP
实现一个简单的基于动态代理的 AOP Intro 上次看基于动态代理的 AOP 框架实现,立了一个 Flag, 自己写一个简单的 AOP 实现示例,今天过来填坑了 目前的实现是基于 Emit 来做的, ...
- 设计模式-原型模式(Prototype)【重点:浅复制与深复制】
讲故事 最近重温了一下星爷的<唐伯虎点秋香>,依然让我捧腹不已,幻想着要是我也能有一名秋香如此的侍女,夫复何求呀,带着这个美好的幻想沉沉睡去... 突然想到,我是一名程序猿呀,想要什么对象 ...