目录

  • @description@
  • @solution@
  • @accepted code@
  • @details@


@description@

请你找到 k 个不同的组合数,使得对于其中任何一个组合数 \(C_a^b\) 有 \(0\leq b\leq a\leq n\)。所谓不同的组合数,即对于组合数 \(C_{a_1}^{b_1}\) 和 \(C_{a_2}^{b_2}\) ,若 \(a_1\neq a_2\) 或者 \(b_1\neq b_2\) ,则我们认为这两个组合数是不同的。问这 \(k\) 个组合数的和最大是多少?

input
第一行两个整数 n, k。

output
一行一个整数,代表 k 个组合数的和对 10^9+7 取模之后的结果;数据保证一定有至少 k 个数可以选。

sample input
2 3
sample output
4

对于 \(20\%\) 的数据,\(n\leq 10\)。
对于 \(40\%\) 的数据,\(n\leq 500\)。
对于另外 \(20\%\) 的数据,\(k=1\)。
对于 \(100\%\) 的数据, \(1\leq n\leq 10^6,1\leq k\leq 10^5\) 。

@solution@

问题相当于求前 k 大的组合数。

当 \(a < b < m/2\) 或 \(a > b > m/2\) 时,有 \(C_{m}^a < C_m^{b}\);
当 \(a < b\) 时,有 \(C_{a}^p < C_{b}^p\)。
这是可以从杨辉三角中看出来的。

我们可以把最大的那个组合数 \(C_n^{n/2}\) 加入优先队列 ,然后向四周扩展。每一次从优先队列中取出最大值 \(C_{a}^{b}\),扩展出 \(C_{a-1}^{b}\), \(C_{a}^{b-1}\),\(C_{a}^{b+1}\),然后将它们加入优先队列。扩展 k 次即可。
同时要注意不要重复经过某一个点。开一个 set 判一下重。

那么问题来了:我们的组合数是取了模的,塞在优先队列里面怎么比较大小呢?逼我写高精度?
这个时候,一个闻所未闻的操作就来了:两边同时取对数
我们组合数公式长这样:
\[C_n^m=\dfrac{n!}{m!*(n-m)!}\]
取完对数长这样:
\[\log_2 C_n^m=\sum_{i=1}^n\log_2 i-\sum_{i=1}^m\log_2 i-\sum_{i=1}^{n-m}\log_2 i\]
(当然底数不一定为 2)
可以发现这个式子是绝对不会溢出的,而且还可以前缀和预处理。
又因为底数大于 1,所以对数的大小关系等同于原数的大小关系。
所以我们就可以比较组合数之间的大小了。

那么问题来了:double 的精度真的不会翻车吗_(:з」∠)_?

@accepted code@

#include<set>
#include<cmath>
#include<queue>
#include<cstdio>
#include<iostream>
using namespace std;
const int MOD = int(1E9) + 7;
const int MAXN = 1000000;
int fct[MAXN + 5], inv[MAXN + 5];
double lgsum[MAXN + 5];
int pow_mod(int b, int p) {int ret = 1;while( p ) {if( p & 1 ) ret = 1LL*ret*b%MOD;b = 1LL*b*b%MOD;p >>= 1;}return ret;
}
void init() {fct[0] = 1;for(int i=1;i<=MAXN;i++)fct[i] = 1LL*fct[i-1]*i%MOD;inv[MAXN] = pow_mod(fct[MAXN], MOD-2);for(int i=MAXN-1;i>=0;i--)inv[i] = 1LL*inv[i+1]*(i+1)%MOD;lgsum[1] = log2(1);for(int i=2;i<=MAXN;i++)lgsum[i] = lgsum[i-1] + log2(i);
}
int C(int n, int m) {return 1LL*fct[n]*inv[m]%MOD*inv[n-m]%MOD;
}
struct node{int n, m;node(int _n=0, int _m=0):n(_n), m(_m){}
};
bool operator < (node a, node b) {if( lgsum[a.n] - lgsum[a.m] - lgsum[a.n - a.m] != lgsum[b.n] - lgsum[b.m] - lgsum[b.n - b.m] )return lgsum[a.n] - lgsum[a.m] - lgsum[a.n - a.m] < lgsum[b.n] - lgsum[b.m] - lgsum[b.n - b.m];else return (a.n == b.n) ? a.m < b.m : a.n < b.n;
}
set<node>Set;
priority_queue<node>que;
int main() {int n, k, ans = 0; init();scanf("%d%d", &n, &k);node s = node(n, n/2);Set.insert(s), que.push(s);for(int i=1;i<=k;i++) {s = que.top(); que.pop();ans = (ans + C(s.n, s.m))%MOD;if( s.m != 0 ) {if( !Set.count(node(s.n, s.m - 1)) )Set.insert(node(s.n, s.m - 1)), que.push(node(s.n, s.m - 1));}if( s.m != s.n ) {if( !Set.count(node(s.n, s.m + 1)) )Set.insert(node(s.n, s.m + 1)), que.push(node(s.n, s.m + 1));if( !Set.count(node(s.n - 1, s.m)) )Set.insert(node(s.n - 1, s.m)), que.push(node(s.n - 1, s.m));}}printf("%d", ans);
}

@details@

重新刷新了 double 的精度问题。
MD 每次我写二分你都卡我精度你这次偏偏不会卡这玩意儿的精度?

取对数这种操作也不是没有见过,《麦森数》那道题就有用到。
看来印象不深刻 QAQ……我果然还是太弱了 QAQ。

转载于:https://www.cnblogs.com/Tiw-Air-OAO/p/10211877.html

@loj - 6353@「CodePlus 2018 4 月赛」组合数问题 2相关推荐

  1. LOJ6299:「CodePlus 2018 3 月赛」白金元首与克劳德斯 (离散化+前缀和)

    题目传送门:https://loj.ac/problem/6299 题目分析:一道不难的题目,然而比赛的时候只有90pts.由于所有克劳德斯(clouds)一开始都不相交,所以答案不是1就是2.用O( ...

  2. loj6300 「CodePlus 2018 3 月赛」博弈论与概率统计

    link 题意: A和B玩游戏,每轮A赢的概率为p.现在有T组询问,已知A赢了n轮输了m轮,没有平局,赢一局A得分+1,输一局得分-1,问A得分期望值? $n+m,T\leq 2.5\times 10 ...

  3. 【LibreOJ】#6299. 「CodePlus 2018 3 月赛」白金元首与克劳德斯

    [题意]给出坐标系中n个矩形,类型1的矩形每单位时间向x轴正方向移动1个单位,类型2的矩形向y轴正方向,初始矩形不重叠,一个点被矩形覆盖当且仅当它在矩形内部(不含边界),求$(-\infty ,+\i ...

  4. 「CodePlus 2018 3 月赛」白金元首与克劳德斯

    所有的云在此时没有重叠的面积 所有的云在此时没有重叠的面积 所有的云在此时没有重叠的面积 所有的云在此时没有重叠的面积 所有的云在此时没有重叠的面积 所有的云在此时没有重叠的面积 所有的云在此时没有重 ...

  5. 【线段树】「CodePlus 2018 3 月赛」白金元首与克劳德斯

    题意: 分析: 题意好鬼扯... 非常傻逼的线段树动态开点题. 横向移动的矩形和纵向移动的矩形,看起来非常麻烦. 由于速度均相等,所以可以以所有纵向移动的矩形为参考系,那么所有纵向移动的矩形都是相对静 ...

  6. 「CodePlus 2017 11 月赛」可做题

    题目描述 qmqmqm 希望给 sublinekelzrip 出一道可做题.于是他想到了这么一道题目:给一个长度为n的非负整数序列ai​​,你需要计算其异或前缀和bi,满足条件b1=a1​​,bi=b ...

  7. LOJ#2833 「JOISC 2018 Day 1」帐篷 dp

    题目描述 译自 JOISC 2018 Day1 T3「テント / Tents」 JOI 君经营着一座露营地.露营地被划分为 H 行 W 列的矩阵,各行平行于东西方向,而各列平行于南北方向.从北向南数第 ...

  8. 「CodePlus 2017 12 月赛」火锅盛宴

    n<=100000种食物,给每个食物煮熟时间,有q<=500000个操作:在某时刻插入某个食物:查询熟食中编号最小的并删除之:查询是否有编号为id的食物,如果有查询是否有编号为id的熟食, ...

  9. LOJ #2838. 「JOISC 2018 Day 3」比太郎的聚会 根号分治

    这道题的数据范围中有两个需要注意到的点: 1. 边都是由编号小的点连向编号大的点. 2. 总点数只有 $10^5$ 个. 所以我们可以考虑采取根号分治的做法: 对于点数大于 $\sqrt n$ 的部分 ...

最新文章

  1. 间谍新高度:航空航天探测器被当作间谍武器
  2. windows 上ping输入到指定文件中
  3. Chromium on Android: 认识Chromium WebView
  4. 开始使用Jenkins
  5. 8月24日云栖精选夜读 | 阿里开源富容器引擎 PouchContainer 的 network 连接机制
  6. MISC-BUUCTF-9题-九连环-佛系青年等
  7. 网络知识:交换机中的半双工与全双工知识笔记
  8. 马斯克超扎克伯格 跻身全球第三大富豪
  9. 【two pointers 细节题】cf1041dD. Glider
  10. VirtualBox安装MACOSX 10.13虚拟机
  11. 免费下载卫星地图 高清卫星地图软件
  12. Python文件指针
  13. C++获取SMART信息
  14. 基督-神[上帝]的道,真理的本真归回
  15. 汉森网络谈谈如何才能增加网站权重
  16. 迭代总结会议的旁观感想
  17. mw325r服务器无响应,水星(MERCURY)路由器MW325R上不了网/连不上网的解决方法
  18. ICLR2021 - Federated Learning Paper
  19. Android加密篇 MD5
  20. atcoder abc284 E

热门文章

  1. shell脚本输出菱形与等边三角形
  2. HDUOJ---1863畅通工程
  3. Cacti 插件中setup.php 文件的编写
  4. java接口的映射文件,详解mybatis通过mapper接口加载映射文件
  5. 【Python-ML】SKlearn库性能指标ROC-AUC
  6. 【正一专栏】最好的回击是打得你好无脾气
  7. Java String关于replaceall函数转义字符的一个小贴士
  8. Tomcat服务OTA发布J2ME应用(eclipse开发环境)
  9. Linux服务器oracle数据库重启服务、重启监听方法,oracle数据库sysdba管理员登录方法
  10. Java 技术篇-mac操作系统JRE、JDK环境的配置演示