若一个大于R的整数J的质因数分解有F项,其最大的质因子为ak,并且满足ak^k≤N,
ak<128,我们就称整数J为N-伪光滑数。
现在给出L,求所有整数中,第E大的N-伪光滑数。
标签:
优先队列乱搞
天哪…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;
}
标签:
原文地址:http://blog.csdn.net/aarongzk/article/details/51628810