题意
找出第N个最小素因子是P的正整数。
若结果超过
109(Maxn)
输出0。
1≤N,P≤109
TimeLimits:1000ms
MemoryLimits:64M
分析
我们很容易想到筛法,因为它能得出每个数的最小质因子。但是
N,P
都很大,只用筛法时间空间必然无法承受。我们考虑将P分类讨论。
假设
Ans=P∗K
我们可以设一个分界
X
当
当
P≤X
时,我们可以二分搜索K,然后用容斥判断该范围内最小质因子大于等于
P
的数的个数是否有
所以我们要找到一个合适的
#include <cstdio>
#include <algorithm>
const int N = 15000010,M = 1e6;
int n,P,tot,cnt,K;
int s[N],prime[M];
void work() {
for (int i = 2;i < N;i ++) {
if (!s[i]) prime[++ tot] = i,s[i] = i;
for (int j = 1;j <= tot && prime[j] * i < N;j ++) {
s[prime[j] * i] = prime[j];
if (i % prime[j] == 0) break;
}
}
}
int calc(int lim) {
int re = 0;
for (int i = 0;i < K;i ++) {
long long cur = 1;
int nt = 0;
for (int S = i,j = 1;S;S >>= 1,j ++) {
if (S & 1) cur *= prime[j],nt ++;
}
if (nt & 1) re -= lim / cur;
else re += lim / cur;
}
return re;
}
int main() {
scanf("%d%d",&n,&P);
work();
if (P > 70) {
int Max = 1e9,r = Max / P,i;
n --;
i = 1;
for (;i <= r && n;i ++) if (s[i] >= P) {
n --;
if (!n) break;
}
if (!n) printf("%d\n",i * P);else printf("0");
}
else {
for (tot = 0;prime[tot + 1] < P; ++ tot);
int l = 0, r = 1e9 / P, ans = 0;
K = 1 << tot;
while (l <= r) {
int mid = (l + r) >> 1;
if (calc(mid) >= n) ans = mid, r = mid - 1;
else l = mid + 1;
}
printf("%d\n",ans * P);
}
}