# Min_25 sift learning notes (pseudo)

Recommended blog: https://blog.csdn.net/qq_33229466/article/details/79679027

Below, the understanding of some corners and corners.

By factoring all the numbers into factoring factors, we consider that the number is classified according to the first prime factor and its number (p^e). We find that the sum of this class can extract a f (p^e) by the nature of the product function, that is, the formula will become f (p^e) (f (a_1 / p^e) + F (a_2 / p^e) +... ) It can be found that the latter part of the formula is a very similar problem. This is probably the main idea of Min_25 sieves.

Specifically, two summation functions are defined. One summation function (h in Zhu Zhenting's paper and G on most blogs on the Internet) assists another evaluation function (that is, G in G papers, and S in most blogs on the Internet).

The evaluation process of the auxiliary evaluation function is very similar to the process of the Ehrlich sieve, so this method is also called the extended Ehrlich sieve method.

Space use only needs O (\sqrt n), because each recursive form is like (all is the division of downward rounding) n - > n / I, N / I - > n / I / J, and the RGP / g / V can be equivalent to (/ *). Number theory is divided into blocks.

What is the complexity of Zhu Zhenting's thesis?

Here are some mathematical formulas (which should be without pots). The code directly sets those formulas. The template is in Counting Divisors.

Product function: $f (x)$

$f (p^e) = \sum_k a_k (E) p^k$is required.

Auxiliary summation function: $h_k (n, J) = \sum_{2 \leq I \leq N and (I's least prime factor > p_j or I is prime number)} If$p_j > \sqrt n$, there is$h_k (n, J) = h_k (n, J - 1) $; Otherwise, there is$h_k (n, J) = h_k (n, J - 1) - p_j^k (h_k (\lfloor \frac n{p_j}\rfloor, j 1) - ((- 1 - 1 -)) $. In particular, for$j = 0$, there is$h_k (n, J) = \sum_{2 \leq I \leq n} i^k$. In short,$h_k (n) = h_k (n, J) $, where$p_j > \sqrt n$(that is, the auxiliary summation function we want finally does not have a combined number). Summation function:$g (n, m) = \sum_{2 \leq I \leq N and (I's least prime factor > p_m)} f (f) $It can be seen that$g (n, m) = \sum_k a_k (1) (H (n) - H (p_m)) + \sum_{p_m < p_j\leq + 1, and + + (+).

If $p_0$is spoken, it will be fine when $0$is processed.

$g (n, 0)$is the requirement.

 #include
#include

typedef unsigned long long u64;

const int MAX_SQRT_N = 1e5;

struct euler_sieve {
static const int MAX_N = MAX_SQRT_N;
bool f[MAX_N + 10];
int p[MAX_N + 10];
int p_n;

inline void operator()(int n) {
memset(f, 0, sizeof f);
p_n = 0;
for (int i = 2; i <= n; ++i) {
if (!f[i]) {
p[++p_n] = i;
}
for (int j = 1; p[j] * i <= n; ++j) {
f[p[j] * i] = true;
if (i % p[j] == 0) break;
}
}
}
} es;

struct Min_25_sieve {
u64 n;

u64 b[2 * MAX_SQRT_N + 10]; // 所有可能的 n / i 值，值是从大到小的（废话）
int b_n, sqrt_n;
inline int locate(u64 i) { return i < sqrt_n ? b_n - i + 1 : n / i; } // 查找 b[j] == i 的位置 j

int d0[2 * MAX_SQRT_N + 10]; // 存储 h 函数的值，数组命名个人癖好而已。  The value of the H function is only O (\sqrt n). The location at I is not h (I), but h (b[i])
inline void pre_calc () {/ / compute h function
for (int = 1; I) = = 1; * = (* 1); / / ((0)). 这里以及下面的 1 * 代表的就是 i^k （本题中 k = 0（不是输入的那个 k 啊））
for (int j = 1; (u64)es.p[j] * es.p[j] <= n; ++j) { // 枚举质数
for (int i = 1; (u64)es.p[j] * es.p[j] <= b[i]; ++i) { // 枚举了有用的，即 b[i]
d0[i] = d0[i] - 1 * (d0[locate(b[i] / es.p[j])] - d0[locate(es.p[j] - 1)]); // 一定有 p[j] - 1 < \sqrt n ，所以一定可以找到一个合法的位置（不会落在一个段内） // 由于 b[i] 的值是从大道小的，所以求值顺序是没有问题的，不用开另外一个缓存数组
}
}
}

u64 f_a0_k;
inline u64 f_a0(int e) { return e * f_a0_k + 1; }
inline u64 f(int p, int e) { return f_a0(e); }

u64 calc(u64 n, int m) { // 计算 g 函数
u64 rst = f_a0(1) * (d0[locate(n)] - d0[locate(es.p[m])]);
for (int j = m + 1; (u64)es.p[j] * es.p[j] <= n; ++j) {
u64 pe = es.p[j];
for (int e = 1; (u64)pe * es.p[j] <= n; ++e, pe *= es .p[j]) {
rst += f(es.p[j], e) * calc(n / pe, j) + f(es.p[j], e + 1);
}
}
return rst;
}

inline u64 operator()(u64 n_, u64 f_a0_k_) {
n = n_;
f_a0_k = f_a0_k_;

// 分块
sqrt_n = 0; while ((u64)sqrt_n * sqrt_n < n) ++sqrt_n;
b_n = 0; for (u64 i = 1; i <= n; i = n / (n / i) + 1) b[++b_n] = n / i;

// 处理辅助求和函数
pre_calc();

// 求和
es.p[0] = 0, d0[b_n + 1] = 0;
return calc(n, 0) + 1; // + 1 是那个甩单的 1
}
} mns;

int main() {
// freopen("in.in", "r", stdin);

int tc; scanf("%d", &tc);
// int tc = 1;
es(MAX_SQRT_N + 5); // 筛出质数
while (tc--) {
u64 n, f_a0_k; scanf("%llu%llu", &n, &f_a0_k);
printf("%llu\n", mns(n, f_a0_k));
}

return 0;
}

This site uses Akismet to reduce spam reviews. Learn how we process your comment data.