若一个大于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; }