BZOJ 4524: [Cqoi2016]伪光滑数

7 篇文章 0 订阅
3 篇文章 0 订阅

和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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值