【bzoj4524】【CQOI2016】【伪光滑数】【堆+贪心】

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
#include
#include
#include
using namespace std;
struct use{long long v;int t,pre,p;}temp;
bool operator<(use a,use b){return a.vq; 
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);
} 


你可能感兴趣的:(堆,贪心)