Description

若一个大于 \(1\) 的整数 \(M\) 的质因数分解有 \(k\) 项,其最大的质因子为 \(Ak\) ,并且满足 \(Ak^K \leq N\) , \(Ak<128\) ,我们就称整数 \(M\) 为 \(N-\) 伪光滑数。现在给出 \(N\) ,求所有整数中,第 \(K\) 大的 \(N-\) 伪光滑数。

Input

只有一行,为用空格隔开的整数 \(N\) 和 \(K\)

\(2 \leq N \leq 10^18\) ,\(1 \leq K \leq 800000\),保证至少有 \(K\) 个满足要求的数

Output

只有一行,为一个整数,表示答案。

Sample Input

12345 20

Sample Output

9167


想法

目前见到的求 第 \(K\) 大/小的题大概有三种做法:

1.二分判断。

2.在 \(K\) 不太大时,可以从大到小/从小到大枚举,用数据结构维护当前最大,取出最大值后用次大值(扩展值)代替它。

3.堆的 \(K\) 路归并(我也不懂这是啥 %%%标算

这道题中我用的是第二种做法。

首先一个性质,对于数 \(i\) ,\(i \leq Ak^k \leq N\) ,假设 \(Ak^k\) 为 \(i\) 的“特征数”

由于 \(Ak \leq 128\) , 而128以内的质数仅31个,所以 \(N\) 以内的特征数值很少

所以大体想法就是优先队列维护所有的“特征数”对应的 \(i\) 的最大值,每次取出最大,用次大替代就行了。

初始状态时每个特征数对应的最大值很好搞,就是 \(Ak^k\) (特征数本身的值)

但次大是多少呢? \(Good\) \(Question!\)

我发现次大有两种情况,一种把一个 \(Ak\) 换为 \(A_{k-1}\),一种是将某一个 \(Ax\) 换为 \(A_{x-1}\)

有点乱。

试着搞出一种扩展顺序,即“分层扩展”。

初始状态,某个特征数 \(Ak^k\) 对应的最大值是 \(k\) 个 \(Ak\) 相乘,不妨称它的层数为0

在扩展 \(Ak^k\) 时,取出一个 \(Ak\) ,换成 \(A1,A2,...,A_{k-1}\) ,即 \(Ak^{k-1} \times Ax\) ,称它们的层数为1(替换了一个 \(Ak\))

在扩展 \(AK^{k-1} \times Ax\) 时,再取出一个 \(Ak\) ,换成 \(A1,A2,...,Ax\) ,即 \(Ak^{k-2} \times Ax \times Ay\) ,称它们的层数为2(替换了两个 \(Ak\))

以此类推……

注意到每次扩展时,\(Ay \leq Ax\) ,这是为了防止同一个数,由于被换的顺序不同而被计算多次。

这样可以保证每次扩展后,该特征数的次大值都在优先队列中嘛?(注意,是“在优先队列中”,但不一定是这次扩展加进去的)

首先,显然每个数扩展出的数都比它本身小,所以对于所有可以通过这种方法扩展出、但没加到优先队列中的数,一定说明扩展出它的数没加到优先队列中或在队列中还没成为最大值,即这些数不是我要的“次大值”

而是不是所有数都可以通过这种方法扩展出呢?显然可以!

其实这就是模拟搜索吧。。。复杂度 \(O(128K)\) 可以卡过。


一些启示

\(Orz\)

分层扩展……?

要有一些顺序的思想吧,不必每次只扩展一个……?

【我也不知道哭唧唧】


代码

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<cmath>
#include<vector> using namespace std; typedef long long ll; ll n;
int k;
int p[31]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127}; struct data{
ll t;
int x,y,z; // p[x]^y,nxtmin--p[z]
data() { t=0; x=y=z=0; }
data(ll a,int b,int c,int d) { t=a; x=b; y=c; z=d; }
bool operator < (const data &b) const{ return t<b.t; }
};
priority_queue<data> q; int main()
{
scanf("%lld%d",&n,&k); ll x;
for(int i=0;i<31;i++){
x=1;
for(int j=1;1ll*x*p[i]<=n;j++){
x*=p[i];
q.push(data(x,i,j,i-1));
}
} data tmp;
while(k--){
tmp=q.top(); q.pop();
if(tmp.y>1){
for(int i=tmp.z;i>=0;i--)
q.push(data(tmp.t/p[tmp.x]*p[i],tmp.x,tmp.y-1,i));
}
}
printf("%lld\n",tmp.t); return 0;
}

[bzoj4524] [loj#2047] [Cqoi2016] 伪光滑数的更多相关文章

  1. 【BZOJ4524】[Cqoi2016]伪光滑数 堆(模拟搜索)

    [BZOJ4524][Cqoi2016]伪光滑数 Description 若一个大于1的整数M的质因数分解有k项,其最大的质因子为Ak,并且满足Ak^K<=N,Ak<128,我们就称整数M ...

  2. @bzoj - 4524@ [Cqoi2016]伪光滑数

    目录 @description@ @solution@ @version - 1@ @version - 2@ @accepted code@ @version - 1@ @version - 2@ ...

  3. [CQOI2016]伪光滑数

    题目描述 若一个大于1的整数M的质因数分解有k项,其最大的质因子为Ak,并且满足Ak^K<=N,Ak<128,我们就称整数M为N-伪 光滑数.现在给出N,求所有整数中,第K大的N-伪光滑数 ...

  4. BZOJ4524 CQOI2016伪光滑数(堆)

    对于每个质数求出其作为最大质因子时最多能有几个质因子,开始时将这些ak1~akmaxk扔进堆.考虑构造方案,使得每次取出最大值后,最大质因子.质因子数均与其相同且恰好比它小的数都在堆里.类似暴搜,对于 ...

  5. BZOJ4524 [Cqoi2016]伪光滑数

    BZOJ上的题面很乱,这里有一个题面. 题解: 正解是可持久化可并堆+DP,可惜我不会... 但暴力也可过这道题. 先在不超过N的前提下,在大根堆里加入每个质数的J次方,1<=j, 然后就可以发 ...

  6. Bzoj 4524 [Cqoi2016]伪光滑数(堆)

    题面 题解 先筛出$<128$的质数,很少,打个表即可 然后钦定一个质数最大,不断替换即可(丢进大根堆里面,然后取出一个,替换在丢进去即可) 具体来说,设一个四元组$[t,x,y,z]$表示当前 ...

  7. 【BZOJ-4524】伪光滑数 堆 + 贪心 (暴力) [可持久化可并堆 + DP]

    4524: [Cqoi2016]伪光滑数 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 183  Solved: 82[Submit][Status] ...

  8. 2021.08.01 P4359 伪光滑数(二叉堆)

    2021.08.01 P4359 伪光滑数(二叉堆) [P4359 CQOI2016]伪光滑数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题意: 若一个大于 11 的整数 MM ...

  9. Loj 2047 伪光滑数

    Loj 2047 伪光滑数 正解较复杂,但这道题其实可以通过暴力解决. 预处理出 \(128\) 内的所有质数,把 \(n\) 内的 \(prime[i]^j\) 丢进堆中,再尝试对每个数变形,除一个 ...

随机推荐

  1. LINUX内核参数调优集锦

    1.linux内核参数注释 2.两种修改内核参数方法 3.内核优化参数生产配置 1.linux内核参数注释 以下表格中红色字体为常用优化参数 根据参数文件所处目录不同而进行分表整理 下列文件所在目录: ...

  2. linux /proc 接口

    无论何时一个硬件中断到达处理器, 一个内部的计数器递增, 提供了一个方法来检查设备 是否如希望地工作. 报告的中断显示在 /proc/interrupts. 下面的快照取自一个双处理 器 Pentiu ...

  3. H3C配置文件的显示与维护

  4. ZR9.8普转提

    ZR9.8普转提 A,B 打过的CF原题,不管了 C 确认过眼神,是我不会写的DP, 发现这个题目要求的过程类似与一个所有括号都不一样的括号匹配的过程 但是限制条件非常多,有点无从下手的感觉 我们设\ ...

  5. Delta Lake源码分析

    目录 Delta Lake源码分析 Delta Lake元数据 snapshot生成 日志提交 冲突检测(并发控制) delete update merge Delta Lake源码分析 Delta ...

  6. Java虚拟机-类文件结构

    目录 类文件结构 Class类文件的结构 魔数与Class文件的版本 常量池 访问标志 类索引.父类索引和接口索引集合 字段表集合 方法表集合 属性表集合 完整结构描述 实例 源码 Class文件 分 ...

  7. Java 学习笔记(11)——多线程

    Java内部提供了针对多线程的支持,线程是CPU执行的最小单位,在多核CPU中使用多线程,能够做到多个任务并行执行,提高效率. 使用多线程的方法 创建Thread类的子类,并重写run方法,在需要启动 ...

  8. sqlserver 2005 备份还原失败

    1.直接右键还原数据库可能会失败.如果失败 使用下面的sql语句还原 USE MASTER RESTORE DATABASE bingo FROM DISK = 'F:\DevProject\bing ...

  9. C++虚继承初识

    struct Employee { ... }; struct Manager : Employee { ... }; struct Worker : Employee { ... }; struct ...

  10. HashMap 原理解析

    HashMap是由数组加链表的结合体.如下图: 图中可以看出HashMap底层就是一个数组结构,每个数组中又存储着链表(链表的引用) JDK1.6实现hashmap的方式是采用位桶(数组)+链表的方式 ...