bzoj4524 [Cqoi2016]偽光滑數 堆
阿新 • • 發佈:2018-12-19
Description
若一個大於1的整數M的質因數分解有k項,其最大的質因子為Ak,並且滿足Ak^K<=N,Ak<128,我們就稱整數M為N-偽光滑數。現在給出N,求所有整數中,第K大的N-偽光滑數。
只有一行,為用空格隔開的整數N和K 2 ≤ N ≤ 10^18, 1 ≤ K ≤ 800000,保證至少有 K 個滿足要求的數
Solution
有點無聊的題
我們列舉最大質數,貪心地把合法的最大質數的次冪扔進堆裡。每次取堆頂然後去掉一個質因數,乘上一個次小的質因數即可 這大概不是正解。不過50多行價效比很高了
Code
#include <stdio.h>
#include <string.h>
#include <set>
#define rep(i,st,ed) for (register int i=st;i<=ed;++i)
typedef long long LL;
const int N=20005;
std:: set <LL> set;
bool not_prime[N];
int prime[N],cnt;
int read() {
int x=0,v=1; char ch=getchar();
for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
for ( ;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
return x*v;
}
void pre_work(int n) {
prime[0]=1;
rep(i,2,n) {
if (!not_prime[i]) prime[++cnt]=i;
for (int j=1;i*prime[j]<=n&&j<=cnt;++j) {
not_prime[i*prime[j]]=1;
if (i%prime[j]==0) break;
}
}
}
int main(void) {
LL n,k; scanf("%lld%lld",&n,&k);
pre_work(128);
rep(i,1,cnt) {
for (LL x=prime[i];x<=n;x*=prime[i]) {
set.insert(x);
}
}
for (;--k;) {
LL s=*set.rbegin(); set.erase(s);
rep(i,1,cnt) if (s%prime[i]==0) {
set.insert(s/prime[i]*prime[i-1]);
}
}
printf("%lld\n", *set.rbegin());
return 0;
}