[bzoj 4524--Cqoi2016]伪光滑数

若一个大于1的整数M的质因数分解有k项,其最大的质因子为Ak,并且满足Ak^K<=N,Ak<128,我们就称整数M为N-伪光滑数。现在给出N,求所有整数中,第K大的N-伪光滑数。

这种问题首先发现一个数是否是伪光滑数只跟它的最大的质因子和分解后的项数有关,而只有31种质因子,所以总共的类别是有限的(把最大的质因子和分解后的项数都相同的归为一类)。
那根据套路开个大根堆,一开始把所有类别的最大值放进去,每取top一次从大到小拓展同类别的数,当然要保证一个数只会被拓展一次。那么结果就为第k次取top的结果。

#include
#include
#include
#include
#include
#include
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0' && ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*f;
}
inline void write(int x)
{
    if(x<0)putchar('-'),x=-x;
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
inline void pr1(int x){write(x),putchar(' ');}
inline void pr2(int x){write(x),puts("");}
struct node
{
    int cnt[35],id,p;long long d;
    node(){memset(cnt,0,sizeof(cnt));}
};
priority_queue<node>q;
bool operator <(node a,node b){return a.d<b.d;}
int sta[35]={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};
int main()
{
    //freopen("a.in","r",stdin);
    //freopen("a.out","w",stdout);
    long long n;int num;
    scanf("%lld%d",&n,&num);num--;
    for(int i=0;i<31;i++)
    {
    	node ul;ul.cnt[i]=1,ul.d=sta[i],ul.id=ul.p=i;
    	while(ul.d<=n){q.push(ul);ul.d*=sta[i],ul.cnt[i]++;}
    }
    while(num--)
    {
    	node uf=q.top();q.pop();
    	for(int i=1;i<=uf.id;i++)
    	{
    		node wy=uf;bool bk=false;
    		if(i==uf.p)
            {
                 if(uf.cnt[i]>1)bk=true;
            }
            else if(uf.cnt[i])bk=true;
    		if(bk==true){wy.d=uf.d/sta[i]*sta[i-1],wy.id=i;wy.cnt[i]--,wy.cnt[i-1]++;q.push(wy);}
    	}
    }printf("%lld\n",q.top().d);
    return 0;
}

你可能感兴趣的:(bzoj,乱搞,bzoj600步)