BZOJ4524 [Cqoi2016]伪光滑数

 BZOJ上的题面很乱,这里有一个题面.

 题解:

 正解是可持久化可并堆+DP,可惜我不会...

 但暴力也可过这道题.

 

 先在不超过N的前提下,在大根堆里加入每个质数的J次方,1<=j,

 然后就可以发现,当前的堆里有着不超过N的最大值.

 然后每次找到堆顶,用这个数除以一次原来的质数乘上一次比它小的质数,把新数全部加入堆中.

 按照这样的方式构造出第K优解.

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<string>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<iomanip>
using namespace std;
#define ll long long
#define db double 
#define up(i,j,n) for(ll i=j;i<=n;i++)
#define pii pair<ll,ll>
#define uint unsigned ll
#define FILE "dealing"
ll read(){
	ll x=0,f=1,ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
	return x*f;
}
template<class T> bool cmax(T& a,T b){return a<b?a=b,true:false;}
template<class T> bool cmin(T& a,T b){return a>b?a=b,true:false;}
const ll maxn=10100,limit=128;
ll n,k;
struct node{
	ll v;
	ll t,pre,p;
	node(ll v=0,ll t=0,ll pre=0,ll p=0):v(v),t(t),pre(pre),p(p){}
}temp;
bool operator<(const node& a,const node& b){return a.v<b.v;}
priority_queue<node> q;
bool b[maxn];
ll prime[maxn],tail=0;
void getprime(){
	up(i,2,128){
		if(!b[i])prime[++tail]=i;
		for(ll j=1;j<=tail&&i*prime[j]<=128;j++){
			b[i*prime[j]]=1;
			if(i%prime[j]==0)break;
		}
	}
	up(i,1,tail){
		ll t=1;
		up(j,1,128){
			if((db)t*prime[i]>n)break;//注意可能爆long long
			q.push(node(t*=prime[i],j,i-1,i));
		}//              data     mi   pre now   
	}
}
int main(){
	freopen(FILE".in","r",stdin);
	freopen(FILE".out","w",stdout);
	n=read(),k=read();
	getprime();
	while(k--){
		temp=q.top();q.pop();
		if(temp.t>1){
			for(ll i=temp.pre;i>=1;i--){
				q.push(node(temp.v/prime[temp.p]*prime[i],temp.t-1,i,temp.p));
			}
		}
	}
	printf("%lld\n",temp.v);
	return 0;
}

  

posted @ 2017-03-15 09:43  CHADLZX  阅读(528)  评论(0编辑  收藏  举报