题面
题解
先筛出$<128$的质数,很少,打个表即可
然后钦定一个质数最大,不断替换即可(丢进大根堆里面,然后取出一个,替换在丢进去即可)
具体来说,设一个四元组$[t,x,y,z]$表示当前的总乘积为$t$,$x$为最大的质数,$y$表示为$x$的多少次方,最后一个$z$表示当前能枚举的右界。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using std::priority_queue;
typedef long long ll;
template<typename T>
void read(T &x) {
int flag = 1; x = 0; char ch = getchar();
while(ch < '0' || ch > '9') { if(ch == '-') flag = -flag; ch = getchar(); }
while(ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); x *= flag;
}
ll N;
int K, p[] = {1, 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 Node { ll t; int x, y, z; };
bool operator < (const Node &a, const Node &b) { return a.t < b.t; }
priority_queue<Node> q;
int main () {
read(N), read(K);
for(int i=1;i<=31;i++) {
ll tmp = p[i];
for(int j = 1; tmp <= N; ++j, tmp *= p[i])
q.push((Node){tmp, p[i], j, i - 1});
}
while(K--) {
Node now = q.top(); q.pop();
if(!K) printf("%lld\n", now.t);
else if(now.y > 1)
for(int i = 1; i <= now.z; ++i)
q.push((Node){now.t / now.x * p[i], now.x, now.y - 1, i});
}
return 0;
}