和D1的K远点对类似的k优解求法
首先找到一个集合使得当前最优解一定在其中
然后每次找到最优解并把与它有关且(必定)劣于它的加到集合里去
重复k-1次
对于这道题显然一开始的集合就是pi^j,pi为质数且pi<128,pi^j<=n
然后每次扩展就是把一个数中的其中一个质因数变小一点
当然还要hash判重
(hash表好像写得有问题QAQ跑得巨慢无比)
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#include<algorithm>
#include<map>
#include<set>
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define per(i,r,l) for(int i=r;i>=l;i--)
#define mmt(a,v) memset(a,v,sizeof(a))
#define tra(i,u) for(int i=head[u];i;i=e[i].next)
using namespace std;
typedef long long ll;
const int M=2000003;
struct Edge{ll to;int next;};
struct Hash_Table{
Edge e[M];int head[M],cnt;
void insert(ll v){
int u=v%M;
e[++cnt]=(Edge){v,head[u]};head[u]=cnt;
}
bool find(ll v){
int u=v%M;
tra(i,u)
if(e[i].to==v)return true;
return false;
}
}h;
int p[40],tot;
bool is[150];
void sieve(){
rep(i,2,127){
if(!is[i])p[++tot]=i;
rep(j,1,tot){
if(p[j]*i>127)break;
is[p[j]*i]=1;
if(i%p[j]==0)break;
}
}
}
struct Node{
ll v;
int cnt[35];
Node(){v=0;mmt(cnt,0);}
bool operator < (const Node &x)const{
return v<x.v;
}
};
priority_queue<Node>q;
int main(){
//freopen("a.in","r",stdin);
sieve();
ll n;int k;
scanf("%lld %d",&n,&k);k--;
rep(i,1,tot){
Node t;
for(t.v=p[i],t.cnt[i]=1;t.v<=n;t.v*=p[i],t.cnt[i]++)
if(!h.find(t.v))
h.insert(t.v),q.push(t);
}
while(k--){
Node t=q.top();q.pop();
rep(i,2,tot)
if(t.cnt[i]){
Node tmp=t;
tmp.cnt[i]--;tmp.cnt[i-1]++;
tmp.v/=p[i];tmp.v*=p[i-1];
if(!h.find(tmp.v))
h.insert(tmp.v),q.push(tmp);
}
}
printf("%lld\n",q.top().v);
return 0;
}