Description
若一个大于R的整数J的质因数分解有F项,其最大的质因子为ak,并且满足ak^k≤N,
ak<128,我们就称整数J为N-伪光滑数。
现在给出L,求所有整数中,第E大的N-伪光滑数。
Input
只有一行,为用空格隔开的整数L和E。
2 ≤ N ≤ 10^18, 1 ≤ K ≤ 800000,保证至少有 E 个满足要求的数
Output
只有一行,为一个整数,表示答案。
Sample Input
12345 20
Sample Output
9167
题解:
首先预处理128之内的所有质数.
把每个质数的1次方,2次方,3次方...加入堆.
然后每次选最大的,选k次.
每次选到一个数.除掉它的最大质因子,乘上一个较小的质因子.
把这些扩展出来的数加入堆即可.
这样堆中需要保存这个数的值,最大质因子的次数,下一次该选的较小质因子的下标,最大质因子的下标.
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
struct use{long long v;int t,pre,p;}temp;
bool operator<(use a,use b){return a.v<b.v;}
priority_queue<use>q;
long long n,t;
int k,p[50],f[200],num,i,j;
int main(){
scanf("%lld%d",&n,&k);
for (i=2;i<=128;i++)
if (!f[i]){p[++num]=i;int t=i;while (t<=128) f[t+=i]=1;}
for (i=1;i<=num;i++)
for (t=j=1;(t*p[i])<=n;j++){
q.push(use{(long long)(t*=p[i]),j,i-1,i});
}
while (k--){
temp=q.top();q.pop();
if (temp.t>1){
for(i=temp.pre;i;i--)
q.push(use{(long long)temp.v/p[temp.p]*p[i],temp.t-1,i,temp.p});
}
}
printf("%lld\n",temp.v);
}