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