GMOJ3188. 【GDOI2013模拟8】找数
作者:互联网
题目大意
找出第 \(n\) 个最小素因子是 \(p\) 的正整数。保证答案 \(\le 10^9\)。
\(n,p\le10^9\)
解题思路
给出一个不用脑子的做法。
根据我们小学二年级就学过的min_25筛,我们可以在 \(O(\frac{n ^ {0.75}}{\log n})\) 对于每一个 \(j\) 得到这个:
其中 \(f(i)\) 是完全积性函数。
你发现用这个就能搞事情。试着做一个差分。
\[g(n,j-1)-g(n,j)=\sum_{i=1}^n[\min_{p|i}p=p_j]-[p_j\le n] \]我们就求出了 \(n\) 以内最小素因子是 \(p\) 的数的个数。你发现二分一下 \(n\) 就做完了。 注意特判 \(j=1\) 的情况。
可以近似看做是 \(O(n^{0.75})\)的。
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
#pragma GCC optimize(2)
#define fo(i, a, b) for(int i = (a); i <= (b); ++i)
const int N = 1e9, M = 32e3;
int tot, p[M], c;
bool v[M + 5];
void pre() {
fo(i, 2, M) {
if(!v[i]) p[++c] = i;
fo(j, 1, c) {
if(p[j] * i > M) break ;
v[p[j] * i] = 1;
if(!(i % p[j])) break ;
}
}
}
int rnk, pr, pj, sq, g[M * 2 + 10], w[M * 2 + 10], id1[M + 10], id2[M + 10];
int getid(int n, int x) {return x <= sq ? id1[x] : id2[n / x];}
bool check(int n) {
int m = 0; sq = sqrt(n);
for(int l = 1, r; l <= n; l = r + 1) {
r = n / (n / l), w[++m] = n / l;
g[m] = w[m] - 1;
w[m] <= sq ? id1[w[m]] = m : id2[n / w[m]] = m;
}
int res = (pr <= n) + (pj == 1 ? n - 1 : 0);
for(int i = 1; i <= pj; ++i) {
for(int j = 1; j <= m && p[i] * p[i] <= w[j]; ++j)
g[j] -= (g[getid(n, w[j] / p[i])] - (i - 1));
if(i == pj) res -= g[1];
if(i == pj - 1) res += g[1];
}
return res >= rnk;
}
int main() {
pre();
scanf("%d %d", &rnk, &pr);
pj = c;
fo(i, 1, c) if(pr == p[i]) pj = i;
int l = 1, r = 1e9, ans = 0, mid;
while(l <= r) {
mid = (l + r) >> 1;
if(check(mid)) r = (ans = mid) - 1;
else l = mid + 1;
}
printf("%d", ans);
return 0;
}
标签:10,min,找数,GMOJ3188,mid,int,ans,include,GDOI2013 来源: https://www.cnblogs.com/Martin-MHT/p/15386153.html