! CQOI2016伪光滑数

堆,贪心


k比较小,我们可以用一个维护,不断更新更大值

发现最大的伪光滑数的所有质因数相同(把一个合法的伪光滑数小的质因数全部换成最大的也满足式子,质因数个数,最大质因数,N均无变化)

堆维护,每次取出最大值,若最大质因数幂次大于1,就把其中一个最大质因数换成较小,再扔进堆里,这样枚举没有遗漏和重复。

当我们取出第k次是即是答案

时间复杂度(O(klog_k))

#include<bits/stdc++.h>
using namespace std;
#define int long long 
inline int read(){
	int x=0,f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	return f==1?x:-x;
}
int n,k,pri[32]={0,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 node{
	int v,p,mi,lim;
	inline bool operator <(const node &a)const{
		return v<a.v;
	}
};
priority_queue<node>q;
signed main(){
	n=read();k=read();
	for(int i=1;i<=31;i++)
		for(int j=1,x=pri[i];x<=n;j++,x=x*pri[i])
			q.push((node){x,pri[i],j,i-1});
	while(k--){
		node x=q.top();q.pop();
		if(!k){cout<<x.v;return (0-0);}
		if(x.mi>1)for(int i=1;i<=x.lim;i++)
			q.push((node){x.v/x.p*pri[i],x.p,x.mi-1,i});
	}
	return (0-0);
}
原文地址:https://www.cnblogs.com/aurora2004/p/12572806.html