Min_25 筛

应用范围:积性函数 \(f\) 可以找到多个完全积性函数 \(g\) 的和与它素数拟合。

\(fac_i\)\(i\) 的最小素因子。
\(p_x\) 为第 \(x\) 大的素数,特别的 \(p_0=1\)
\(\mathcal{P}\) 素数集。
\(\mathcal{P}(n)\) \(n\) 以内素数个数。

设: $$Sg(n,x) = \sum_{i \in \mathcal{P} \vee fac_i > p_x}^{n}g(i)$$

特别的:$$Sg(n, 0) = \sum_{i=2}^n g(i)$$

考虑转移方程 \(Sg(n,x)\) 就是 \(Sg(n,x-1)\) 减去最小素因子为 \(p_x\) 的合数的 \(g\) 和。而 \(Sg(p_x,x)\) 就是前 \(x\) 个质数的 \(g\) 和,由于 \(p_x \le \sqrt{N}\),最开始线性筛递推预处理就可以,体现在 code 中就是 Gp1/2[]

这里算 \(n\) 以内最小素因子为 \(p_x\) 的合数的 \(g\) 和,可以提前选一个质因数 \(p_x\),根据完全积性函数的优美性质,就可以转化为子问题:在 \(\frac{n}{p_x}\) 选最小素因子 \(\ge p_x\) 的合数的 \(g\) 和, 最后再乘上 \(g(p_x)\) 就是答案,注意减去质数的 \(g\)

\[Sg(n,x) = Sg(n,x-1)-g(p_x)(Sg([\frac{n}{p_x}],x-1) - Sg(p_{x-1},x-1)) \]

因为 \(n\) 以内合数的最小素因子 \(\le \sqrt{n}\),只用枚举到 \(\max\{x|p_x^2 \le n\}\)。又因为后面只会调用 \(g([\frac{N}{x}],pc)\),这里还可以滚动数组,把 \(x\) 这一维滚动掉,仅保留 \(x=\mathcal{P}(n)\)\(g\),同时仅枚举 \(n=[\frac{N}{x}]\),这样保证状态数仅有 \(\mathcal{O}(\frac{N^{\frac{3}{4}}}{\log_2 N})\)

现在用 \(Sg\)\(Sf\),设: $$S_f(n,x) = \sum_{fac_i>p_x}^{n}f(i)$$

  • 对于满足 \(i \in \mathcal{P} \wedge fac_i > p_x\) 的数 \(i\),这些数的贡献为 \(Sg(n,x) - Sg(p_x,x)\)

  • \(\operatorname{Otherwise.}\),枚举它们的最小素因子 \(p_i\) 和其次数 \(k\)(枚举次数是因为这里 \(f\) 不是完全积性函数),仿造上文 \(g\) 的转移转化为子问题。

所以有转移方程:

\[Sf(n,x) = Sg(n,x) - Sg(p_x,x) + \sum_{i=x+1}^{p_i\le\sqrt{n}}\sum_{k=1}^{p_i^k\le n}f(p_i^k)(Sf(\frac{n}{p_i^k},i)+[k \ne 1]) \]

\([k \ne 1]\): 是因为 \(Sf\) 计算的和不包括 \(1\),需要单独加入。

暴力就行了,复杂度 \(\mathcal{O}(\frac{N^{\frac{3}{4}}}{\log_2 N})\)

另一份笔记

Example LG5325

namespace MG42 {
    int n, V, factor[N], prime[N], pc = 0, lsh[N], lshc = 0, Gp1[N], Gp2[N], G1[N], G2[N], inv2 = 500000004, inv6 = 166666668;
    int id1[N], id2[N];
    inline int idx(int x) {return x <= V ? id1[x] : id2[n / x];}
    inline ll S1(int n) {return n %= P, n * (n + 1) % P * inv2 % P;}
    inline ll S2(int n) {return n %= P, n * (n + 1) % P * (2 * n + 1) % P * inv6 % P;}
    inline void sieve(int n) {
        V = ceil(sqrt(n)), pc = lshc = 0, prime[0] = 1;
        REP(i, 2, V) {
            if (!factor[i]) prime[++pc] = factor[i] = i, Gp1[pc] = (Gp1[pc - 1] + i) % P, Gp2[pc] = (Gp2[pc - 1] + i * i) % P;
            for (int j = 1; j <= pc && i * prime[j] <= V; ++j) {factor[i * prime[j]] = prime[j]; if (factor[i] == prime[j]) break;}
       }
        for (int l = 1, r = 0; l <= n; l = r + 1) r = n / (n / l), lsh[++lshc] = n / l, G1[lshc] = (S1(n / l) + P - 1) % P, G2[lshc] = (S2(n / l) + P - 1) % P, (n / l <= V ? id1[n / l] = lshc : id2[n / (n / l)] = lshc); 
        REP(i, 1, pc) {
            for (int j = 1; j <= lshc && prime[i] * prime[i] <= lsh[j]; ++j) {
                (G1[j] -= prime[i] *                (G1[idx(lsh[j] / prime[i])] - Gp1[i - 1])) %= P;
                (G2[j] -= prime[i] * prime[i] % P * (G2[idx(lsh[j] / prime[i])] - Gp2[i - 1])) %= P;
            }
        }
    }
    inline ll f(ll x) {return (x % P) * ((x % P) - 1) % P;}
    inline ll F(int n, int x, ll _ = 0) {
        if (prime[x] >= n) return 0;
        _ = ((G2[idx(n)] - Gp2[x]) - (G1[idx(n)] - Gp1[x])) % P; // prime number
        for (int i = x + 1; i <= pc && prime[i] * prime[i] <= n; ++i) for (int j = prime[i]; j <= n; j *= prime[i]) 
            (_ += f(j) * (F(n / j, i) + (prime[i] != j))) %= P;
        return _;
    }
    signed main() {
        ld >> n, sieve(n);
        return jyt << (F(n, 0) + 1 + P) % P << '\n', 0; 
    }
}
posted @ 2025-02-11 20:12  flowing_boat  阅读(33)  评论(1)    收藏  举报