Smooth——题解

版权声明:发现蒟蒻ff_666,但转载请注明 https://blog.csdn.net/qq_42403731/article/details/82220686

题目大意

求第K大的B-光滑数
其中如果一个数的最大质因子不超过 p B (p代表素数),就称它是一个 B-光滑数(1是最小的光滑数
K <= 10 7 , B <= 15 2 s

题解

乍一看,这题不就是著名经典问题——丑数吗?
(然而实际上它就是丑数。。)

显然,我们可以用一个小根堆来存储当前生出的满足条件的B-光滑数
那么每次取出堆顶,贪心想法,由当前解 x 生出的下一个B-光滑数一定是 x p i
然后取K-1次,就OK了
还可以加一道优化:当前已经取过i个,那么显然接下来还要取K-1-i个
——所以假如当堆中有这么多元素,那么大于当前堆中最大元素的元素再往里塞根本没有意义,就不塞了(至于这个最大值,显然可以在塞的时候 O ( 1 ) 维护)
然后有赖于HHHOJ的神速,我这样都能惊险卡过。。
复杂度 O ( K B log K B )

#include<cstdio>
#include<algorithm>
#define LL long long
using namespace std;
const int p[]={0,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47};
const int maxn=(1e7)+5;
int k,b,len;LL max_x;
struct ff{
    int lst;LL x;
    inline bool operator <(const ff j)const{return j.x<x;}
}hep[maxn<<1];
inline void put(ff x){hep[++len]=x,push_heap(hep+1,hep+1+len);if(x.x>max_x) max_x=x.x;}
inline ff get(){return pop_heap(hep+1,hep+1+len),hep[len--];}
int main(){
    scanf("%d%d",&b,&k);
    for(int i=1;i<=b;i++) put((ff){i,p[i]});
    ff j;LL now;
    for(int i=1;i<k;i++){
        j=get();
        for(int t=j.lst;t<=b;t++) if((now=j.x*p[t])>=max_x&&len>=k-1-i) break;else put((ff){t,now});
    }
    printf("%lld\n",j.x);
    return 0;
}

然后考虑优掉堆的log
当我们已知前k个数,想得到第k+1个,我们可以这样做:对于每个质数 p i ,寻找最小的数,使得 h j p i 比上一个丑数大,则下一个数就为 m i n ( h j p i )
显然对于每一个质数 p i 来说, h j 是递增的,即 j 是不断增大的
所以为了使搜索更快,我们可以为每个质数维护一个索引lst,表示每个质数已经乘到了哪个数,每次都从那里开始,而不是再从头再来。

实现就很简单了:
——当求第i个数时,先枚举质数 p i ,一趟 O ( B ) 的循环求出当前第i个数为 m i n ( h l s t i p i ) > h i 1 ,然后更新lst指标

复杂度稳稳的 O ( K B )

#pragma GCC optimize(436)
#include<cstdio>
#define LL long long
using namespace std;
const int maxn=(1e7)+5,p[]={0,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47};
int k,b,lst[30];LL h[maxn];
int main(){
    scanf("%d%d",&b,&k);
    h[0]=1;
    for(int i=1;i<k;i++){
        h[i]=h[lst[1]]*p[1];
        for(int j=2;j<=b;j++) if(h[lst[j]]*p[j]<h[i]) h[i]=h[lst[j]]*p[j];
        for(int j=1;j<=b;j++) if(h[lst[j]]*p[j]==h[i]) lst[j]++;
    }
    printf("%lld\n",h[k-1]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_42403731/article/details/82220686