bzoj4524【CQOI2016】伪光滑数

4524: [Cqoi2016]伪光滑数

Time Limit: 10 Sec   Memory Limit: 512 MB
Submit: 257   Solved: 117
[ Submit][ Status][ Discuss]

Description

若一个大于R的整数J的质因数分解有F项,其最大的质因子为ak,并且满足ak^k≤N,
ak<128,我们就称整数J为N-伪光滑数。
现在给出L,求所有整数中,第E大的N-伪光滑数。

Input

只有一行,为用空格隔开的整数L和E。
2 ≤ N ≤ 10^18, 1 ≤ K ≤ 800000,保证至少有 E 个满足要求的数

Output

只有一行,为一个整数,表示答案。

Sample Input

12345 20

Sample Output

9167



优先队列乱搞

天哪…CQOI2016的乱搞题好多orz

定义一个四维状态(t,x,y,z)表示当前的数为t,最大的质因数是x,x的次数是y,还可以加入的质因数最大是第z个质数。

有一个很显然的性质,如果最大的质数和质因数确定了,一定是尽可能多的选择最大的质数。所以初始状态是(x^y,x,y,z),满足x^y≤n,z等于小于x的质数的个数。

然后每次从优先队列中拿出最大的一个数,加入对应的状态是(t,x,y,z),如果y>1则从1-z中取出一个质数替换掉一个x,再加入优先队列中。

这样的操作保证了一定可以找到最大的k个数。

(表达能力好水...还是看代码吧)




#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
using namespace std;
int k,cnt,p[150];
ll n;
bool vst[150];
struct data{ll t,x,y,z;};
bool operator <(data a,data b){return a.t<b.t;}
priority_queue<data> q;
int main()
{
	scanf("%lld%d",&n,&k);
	F(i,2,128) if (!vst[i])
	{
		p[++cnt]=i;ll x=i;
		for(int j=1;x<=n;j++,x*=i) q.push((data){x,i,j-1,cnt-1});
		F(j,2,128/i) vst[i*j]=true;
	}
	F(i,1,k)
	{
		data tmp=q.top();q.pop();
		if (i==k){printf("%lld\n",tmp.t);return 0;}
		if (tmp.y) F(j,1,tmp.z) q.push((data){tmp.t/tmp.x*p[j],tmp.x,tmp.y-1,j});
	}
	return 0;
}


你可能感兴趣的:(优先队列,bzoj)