题意:给你一个大整数X的素因子分解形式,每个因子不超过m。问你能否找到两个数n,k,k<=n<=m,使得C(n,k)=X。

不妨取对数,把乘法转换成加法。枚举n,然后去找最大的k(<=n/2),使得ln(C(n,k))<=ln(X),然后用哈希去验证是否恰好等于ln(X)。

由于n和k有单调性,所以枚举其实是O(m)。

妈的这个哈希思想贼巧妙啊,因为对数使得精度爆炸,所以不妨同步弄个哈希值,来判相等。

opencup的标程:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <algorithm>
  5. #include "bits/stdc++.h"
  6. using namespace std;
  7.  
  8. using UInt = unsigned long long;
  9. using Float = long double;
  10.  
  11. const int M = 150 * 1000;
  12.  
  13. Float LogSum[M+1];
  14. UInt Hash[M+1];
  15. UInt HashSum[M+1];
  16.  
  17. void Init(int m) {
  18. // LogF
  19. LogSum[0] = 0.;
  20. for (int i = 1; i <= m; ++i) {
  21. LogSum[i] = LogSum[i-1] + log((Float) i);
  22. }
  23.  
  24. // Hash, HashF
  25. std::mt19937 gen;
  26. uniform_int_distribution<UInt> distr;
  27. vector<int> sieve(m+1, 0);
  28. for (int i = 2; i * i <= m; ++i) {
  29. if (sieve[i] == 0) {
  30. for (int j = i * i; j <= m; j += i) {
  31. sieve[j] = i;
  32. }
  33. }
  34. }
  35. Hash[0] = Hash[1] = 0;
  36. for (int i = 2; i <= m; ++i) {
  37. if (sieve[i] == 0) {
  38. Hash[i] = distr(gen);
  39. } else {
  40. Hash[i] = Hash[i/sieve[i]] + Hash[sieve[i]];
  41. }
  42. }
  43. partial_sum(Hash, Hash + m + 1, HashSum);
  44. }
  45.  
  46. Float LogBinom(int n, int k) {
  47. return LogSum[n] - LogSum[n-k] - LogSum[k];
  48. }
  49.  
  50. UInt HashBinom(int n, int k) {
  51. return HashSum[n] - HashSum[n-k] - HashSum[k];
  52. }
  53.  
  54. bool Solve(const vector<int>& factors, int m, int& n, int& k) {
  55. for (int p : factors) {if (p > m) { return false; }}
  56. Float log_x = 0;
  57. UInt hash_x = 0;
  58. for (int p : factors) { log_x += log((Float) p); hash_x += Hash[p]; }
  59.  
  60. //check
  61. int b = m;
  62. for (int a = 0; a <= m; ++a) {
  63. while (b > 0 && (a + b - 1 > m || LogBinom(a+b-1, a) >= log_x)) { --b; }
  64. if (b > 0 && HashBinom(a + b - 1, a) == hash_x) {
  65. n = a + b - 1;
  66. k = a;
  67. return true;
  68. }
  69. if (a + b <= m && HashBinom(a+b, a) == hash_x) {
  70. n = a + b;
  71. k = a;
  72. return true;
  73. }
  74. }
  75. return false;
  76. }
  77.  
  78. int main() {
  79. Init(M);
  80. ios_base::sync_with_stdio(false);
  81. int z;
  82. cin >> z;
  83. while (z--) {
  84. int t;
  85. int m;
  86. cin >> t >> m;
  87. vector<int> factors(t);
  88. for (int i = 0; i < t; ++i) {
  89. cin >> factors[i];
  90. }
  91.  
  92. //assert(t != 0);
  93. int n, k;
  94. if (Solve(factors, m, n, k)) {
  95. cout << "YES\n";
  96. cout << n << ' ' << k << '\n';
  97. } else {
  98. cout << "NO\n";
  99. }
  100. }
  101. }

【取对数】【哈希】Petrozavodsk Winter Training Camp 2018 Day 1: Jagiellonian U Contest, Tuesday, January 30, 2018 Problem J. Bobby Tables的更多相关文章

  1. 【模拟退火】Petrozavodsk Winter Training Camp 2017 Day 1: Jagiellonian U Contest, Monday, January 30, 2017 Problem F. Factory

    让你在平面上取一个点,使得其到给定的所有点的距离和最小. 就是“费马点”. 模拟退火……日后学习一下,这是从网上扒的,先存下. #include<iostream> #include< ...

  2. 【动态规划】【二分】Petrozavodsk Winter Training Camp 2017 Day 1: Jagiellonian U Contest, Monday, January 30, 2017 Problem B. Dissertation

    题意: 给定S1串,长度100w,S2串,长度1k.问它俩的LCS. f(i,j)表示S2串前i个字符,LCS为j时,最少需要的S1串的前缀长度.转移的时候,枚举下一个字符在S1的位置即可.(可以预处 ...

  3. 【二分】Petrozavodsk Winter Training Camp 2017 Day 1: Jagiellonian U Contest, Monday, January 30, 2017 Problem A. The Catcher in the Rye

    一个区域,垂直分成三块,每块有一个速度限制,问你从左下角跑到右上角的最短时间. 将区域看作三块折射率不同的介质,可以证明,按照光路跑时间最短. 于是可以二分第一个入射角,此时可以推出射到最右侧边界上的 ...

  4. 【状压dp】Petrozavodsk Winter Training Camp 2018 Day 1: Jagiellonian U Contest, Tuesday, January 30, 2018 Problem E. Guessing Game

    题意:给你n个两两不同的零一串,Alice在其中选定一个,Bob去猜,每次询问某一位是0 or 1.问你最坏情况下最少要猜几次. f(22...2)表示当前状态的最小步数,2表示这位没确定,1表示确定 ...

  5. 【BFS】【最小生成树】Petrozavodsk Winter Training Camp 2018 Day 1: Jagiellonian U Contest, Tuesday, January 30, 2018 Problem G. We Need More Managers!

    题意:给你n个点,点带权,任意两点之间的边权是它们的点权的异或值中“1”的个数,问你该图的最小生成树. 看似是个完全图,实际上有很多边是废的.类似……卡诺图的思想?从读入的点出发BFS,每次只到改变它 ...

  6. 【推导】【单调性】Petrozavodsk Winter Training Camp 2018 Day 1: Jagiellonian U Contest, Tuesday, January 30, 2018 Problem B. Tribute

    题意:有n个数,除了空集外,它们会形成2^n-1个子集,给你这些子集的和的结果,让你还原原来的n个数. 假设原数是3 5 16, 那么它们形成3 5 8 16 19 21 24, 那么第一轮取出开头的 ...

  7. 【线性基】Petrozavodsk Winter Training Camp 2018 Day 1: Jagiellonian U Contest, Tuesday, January 30, 2018 Problem A. XOR

    题意:给你一些数,问你是否能够将它们划分成两个集合,使得这两个集合的异或和之差的绝对值最小. 设所有数的异或和为S,集合A的异或和为A. 首先,S的0的位对答案不造成影响. S的最高位1,所对应的A的 ...

  8. 【推导】【构造】Petrozavodsk Summer Training Camp 2015 Day 2: Xudyh (TooSimple) Contest, Saturday, August 22, 2015 Problem G. Travelling Salesman Problem

    一个矩阵,每个位置有一个非负整数,一个人从左上走到右下,不能走重复的格子,问得到的最大权值. 当长宽不都为偶数时,必然能走遍所有格子,横着从左到右,从右到左(或是竖着走)走完即可. 当长宽都是偶数时, ...

  9. 2015 UESTC Winter Training #7【2010-2011 Petrozavodsk Winter Training Camp, Saratov State U Contest】

    2015 UESTC Winter Training #7 2010-2011 Petrozavodsk Winter Training Camp, Saratov State U Contest 据 ...

随机推荐

  1. Servlet笔记6--Servlet程序改进

    第一步改进,GenericServlet: 我们目前所有放入Servlet类直接实现了javax.servlet.Servlet接口,但是这个接口中有很多方法是目前不需要的,我们可能只需要编写serv ...

  2. oracle主键约束、唯一键约束和唯一索引的区别

    (1)主键约束和唯一键约束均会隐式创建同名的唯一索引,当主键约束或者唯一键约束失效时,隐式创建的唯一索引会被删除: (2)主键约束要求列值非空,而唯一键约束和唯一索引不要求列值非空: (3)相同字段序 ...

  3. 使用IntelliJ IDEA新建maven的javaWeb项目部署,启动访问index,jsp页面

    对于用惯了eclipse的人,idea其实还挺不一样的,也是摸索了很久,看了好多博客,这里就记录一下,以后肯定经常用!,不过使用熟练了,功能确实非常强大,真的牛! 1 新建maven项目,配置好目录结 ...

  4. 【codeforces】【比赛题解】#861 CF Round #434 (Div.2)

    本来是rated,现在变成unrated,你说气不气. 链接. [A]k-凑整 题意: 一个正整数\(n\)的\(k\)-凑整数是最小的正整数\(x\)使得\(x\)在十进制下末尾有\(k\)个或更多 ...

  5. torch.Tensor.view (Python method, in torch.Tensor)

    返回具有相同数据但大小不同的新张量.返回的张量共享相同的数据,必须具有相同数量的元素,但可能有不同的大小. Example >>> x = torch.randn(4, 4) > ...

  6. 关于oracle数据库死锁的检查方法

    一.数据库死锁的现象程序在执行的过程中,点击确定或保存按钮,程序没有响应,也没有出现报错. 二.死锁的原理当对于数据库某个表的某一列做更新或删除等操作,执行完毕后该条语句不提交,另一条对于这一列数据做 ...

  7. window.print打印方法实现

    vue中使用window.print打印效果 项目要求 打印每页有10行表格,如果接口数据没有十个显示10行 效果图 第一页 第二页 子组件 <template> <div> ...

  8. poj1077

    题意:给出一个八数码问题,求解法,不可解则输出unsolvable. 分析:可以用ida*算法,估价函数可以使用每个数码到其最终位置的最短距离之和.对于不可解的判断,我这里用迭代深度大于100时判定为 ...

  9. poj3636

    题意:每个物品有两个属性:长和宽(长宽不可互换).如果一个物品的长和宽均大于另一个物品,则这个物品可以罩住另一个物品,用这种罩住物品的方法将物品分组,一组之内的物品可以一个罩住一个的全部罩起来.问最少 ...

  10. ubuntu 创建容器 并ssh 连接容器

    1.下载镜像:docker search ubuntu docker pull ubuntu 2. 创建容器 docker run --name spider_frame -p 8888:8888 - ...