BZOJ 4524: [Cqoi2016]伪光滑数

题意杀233,开始我习惯地认为质因数分解就是那种\(2^{a_1}\times 3^{a_2}\times \cdots \times p_k^{a_k}\)的形式,然后\(p_k^{a_k}\)算作一项,苦想了30min无果

然后看了下陈指导的博客,NMD原来上面的指数要展开的!(好吧这样本来也就是展开来的缩写),然后就会做了

首先要求前\(K\)大,先考虑最大的情况。不难发现这个时候所有质因数都相同显然是最优的,因为如果不相同那么我们必然可以把不是最大的那些质因数全部换成最大的而满足\(A_k^k\)不变

那么就很容易了,我们搞出\(< 128\)的所有质数,然后把它们的幂次都扔到堆里去,考虑如何更新答案

由于现在的质因数都是相同的且最大的,那么我们肯定是在保证最大质因数项数不变的情况下让这个数本身变小,那么就是把其中的一个最大质因数换成更小的即可

然后为了避免重复,我们还需要控制一个范围,表示枚举的替换的质因数的范围,同时还要保证替换之后这个最大质因数的幂次至少是\(1\)(废话)

然后我们开一个四元组表示上面提到的状态即可

#include<cstdio>
#include<queue>
#define RI register int
#define CI const int&
using namespace std;
typedef long long LL;
const int prime[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 val; int prm,lim,tim; //当前值,最大质数,下个枚举的范围,这个质数的幂次
    friend inline bool operator < (const data& A,const data& B)
    {
        return A.val<B.val;
    }
}; priority_queue <data> hp; LL n; int k;
int main()
{
    RI i,j; for (scanf("%lld%d",&n,&k),i=0;i<31;++i)
    for (LL cur=prime[i],ct=1;cur<=n;cur=cur*prime[i],++ct)
    hp.push((data){cur,prime[i],i-1,ct}); for (i=1;i<k;++i)
    {
        data now=hp.top(); hp.pop();
        if (now.tim>1) for (j=0;j<=now.lim;++j)
        hp.push((data){now.val/now.prm*prime[j],now.prm,j,now.tim-1});
    }
    return printf("%lld",hp.top().val),0;
}
posted @ 2020-01-29 17:38  空気力学の詩  阅读(91)  评论(0编辑  收藏  举报