BZOJ 4524: [Cqoi2016]僞光滑數

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


發佈了293 篇原創文章 · 獲贊 3 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章