杜教筛入门

以下主要的话都用无序列表表示。

诶,是不是应该先讲背景

有什么好讲的?

问一个积性函数的前缀和,项数到1e10。

前置知识

线性筛积性函数

正文

钦定你已经可以再\(O(\sqrt{n})\)的复杂度内求出:

\[\sum_{i=1}^n{\lfloor \frac{n}{i} \rfloor}\]

\[\sum_{i=1}^n{i\times \lfloor \frac{n}{i} \rfloor}\]

对于第一个,先枚举小于\(\sqrt n\)的i,得出这段的值;又因为\(i\)在一段区间内\(\lfloor \frac{n}{i} \rfloor\)都是\(i_0\leq \sqrt n\),因此可以求前式和后式。

  • 形式化地讲,若\(\sum_{i=1}^n{f(i)\times g(\lfloor \frac{n}{i} \rfloor)}\)中,若能方便的求得\(f(i)\)的前缀和以及\(g(x)\),就能方便的求得原式。

然后对于积性函数\(f(i)\),我们想求\(S_n=\sum_{i=1}^n{f(i)}\)。

那么,我们找一个积性函数\(g\),令\(T_n=\sum_{d\mid n}g(d)\times f(\frac{n}{d})\)(就是狄利克雷卷积)。则有:
\[
\begin{aligned}
\sum_{i=1}^n{T_i} & =\sum_{i=1}^n \sum_{d\mid i}{g(d)\times f(\frac{i}{d})} \ & =\sum_{d=1}^n{g(d)\times \sum_{d\mid i, i\leq n}{f(\frac{i}{d})}} \ & =\sum_{d=1}^n{g(d)\times S_{\lfloor \frac{n}{d} \rfloor}}
\end{aligned}
\]

然后,钦定\(g(1)=1\),那么就有
\[
\begin{aligned}
S_n & =\sum_{d=1}^n{g(d)\times S_{\lfloor \frac{n}{d} \rfloor}}-\sum_{d=2}^n{g(d)\times S_{\lfloor \frac{n}{d} \rfloor}} \ & =\sum_{i=1}^n{T_i}-\sum_{d=2}^n{g(d)\times S_{\lfloor \frac{n}{d} \rfloor}}
\end{aligned}
\]

如果不管怎么求\(S_{\lfloor \frac{n}{d} \rfloor}\)的话,发现满足以下两个条件就可以求\(S_n\)了。

  • 可以求g的前缀和
  • 可以求T的前缀和

考虑怎么求上式后面的\(S_{\lfloor \frac{n}{d} \rfloor}\),由于f是积性函数,必定可以用线性筛筛出前n项,于是可以用线性筛筛了f求出\(S_{1..\sqrt n}\),至于大于\(\sqrt{n}\)的下标,可以记搜:因为\(\lfloor \frac{\lfloor \frac{n}{d} \rfloor}{e} \rfloor=\lfloor \frac{n}{d\times e} \rfloor\),于是可以记录n/d的d,当\(d>\sqrt{n}\)时直接返回结果就行。

  • 于是,求前缀和成功转化成用人类智慧求一个g。

模板题

对于\(\phi\),g为1(常值函数),T为i(自然数序列),用到的结论是\(x=\sum_{d\mid x}{phi_d}\)。

证明有这样几个方向:

  1. 证明\(\forall i\mid n,1\leq j<i,(i,j)=1\),都有\(i_1\times j_1\neq i_2\times j_2\)。显然是要被叉翻的(其实是我在用3时不知道干嘛了)。
  2. 直接通过\(\phi\)的计算公式和积性通过一波推理得到一些式子,化简得到n。(巨佬做法)
  3. 证明\(\forall i\mid n,1\leq j<i,(i,j)=1\),都有\(n/i_1\times j_1\neq n/i_2\times j_2\)。显然,因为互质,所以两个都是最简分数,于是当i,j不同时,分数不可能相等,于是证明了任意一个\(x\in [1,n]\)都只能由一个(i,j)对转移而来,即一一对应,证毕。

以上2的证明:
\[
\begin{aligned}
\sum_{d\mid n}{\phi(d)} & =\sum{\phi(\prod_{i=1}^m{p_i^j})} \ & =\sum{\prod_{i=1}^m{\phi(p_i^j)}} \ & =\prod_{i=1}^m{\sum_{j=0}^{a_i}{\phi(p_i^j)}} \ & =\prod_{i=1}^m{(\sum_{j=1}^{a_i}{(p_i^j-p_i^{j-1})}+1)} \ & =\prod_{i=1}^m{p_i^{a_i}}=n
\end{aligned}
\]

然后写出来就可以了。

以下是一份跑的非常慢的代码模板(洛谷模板题的关键代码)。

const int N = 3000005, nn = 3000000;
struct getSum{
    ll presum[N], aftersum[N];
    bool calced[N];
    inline ll sum(int n,int d,ll sT(int),ll sg(int),ll g(int)){
        if (n / d <= nn) return presum[n / d];
        if (calced[d]) return aftersum[d];
        int nn = n / d;
        ll ans = sT(nn);
        ans -= (sg(nn) - sg(nn / 2)) * presum[1];
        REP(i, 2, floor(sqrt(nn))){
            ans -= g(i) * sum(n, d * i, T, b, g);
            ans -= (sg(nn / i) - sg(Max(nn / (i + 1), i))) * presum[i];
        }
        calced[d] = 1;
        aftersum[d] = ans;
        return ans;
    }
};
int T, n;
int b[N];
ll phi[N], miu[N];
int temp[N / 10], top;
int main(){
    read(T);
    phi[1] = miu[1] = 1;
    REP(i, 2, nn){
        if (!b[i]){
            temp[++top] = i;
            phi[i] = i - 1;
            miu[i] = -1;
        }
        for (int j = 1; j <= top && i * temp[j] <= nn; ++j){
            b[i * temp[j]] = 1;
            if (i % temp[j]){
                phi[i * temp[j]] = phi[i] * (temp[j] - 1);
                miu[i * temp[j]] = -miu[i];
            }
            else{
                phi[i * temp[j]] = phi[i] * temp[j];
                miu[i * temp[j]] = 0;
                break;
            }
        }
    }
    REP(i, 2, nn){
        phi[i] = phi[i] + phi[i - 1];
        miu[i] = miu[i] + miu[i - 1];
    }
    memcpy(van.presum, phi, 8 * (nn + 1));
    memcpy(deep.presum, miu, 8 * (nn + 1));
    while (T--){
        read(n);
        mem(van.calced);
        printf("%lld ", van.sum(n, 1, [](int n) { return 1LL * n * (n + 1) / 2; }, [](int n) { return 1LL * n; }, [](int n) { return 1LL; }));
        mem(deep.calced);
        printf("%lld\n", deep.sum(n, 1, [](int n) { return 1LL; }, [](int n) { return 1LL * n; }, [](int n) { return 1LL; }));
    }
    return 0;
}

原文地址:https://www.cnblogs.com/pupuvovovovo/p/11679401.html

时间: 2024-10-09 07:20:38

杜教筛入门的相关文章

●杜教筛入门(BZOJ 3944 Sum)

入门杜教筛啦. http://blog.csdn.net/skywalkert/article/details/50500009(好文!) 可以在$O(N^{\frac{2}{3}})或O(N^{\frac{3}{4}})$的复杂度内解决求某些数论函数f(n)(或f的前缀和S(n)$)的值. 先来看看原理是什么.(接下来推导如何求数论函数f(n)的前缀和S(n)) 现在有两个数论函数$f( )和g( )$ (同时定义f的前缀和函数$S(n)=\sum_{i=1}^{n}f(i)$) 有狄利克雷乘

bzoj 3944 Sum —— 杜教筛

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3944 杜教筛入门题! 看博客:https://www.cnblogs.com/zjp-shadow/p/8491542.html 写法模仿其他博客的,但很慢啊... 代码如下: #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<ma

数论入门——莫比乌斯函数,欧拉函数,狄利克雷卷积,线性筛,莫比乌斯反演,杜教筛

一个菜鸡对数论的一点点理解... 莫比乌斯函数 定义函数\(\mu(n)\)为: 当n有平方因子时,\(\mu(n)=0\). 当n没有平方因子时,\(\mu(n)=(-1)^{\omega(n)}\),\(\omega(n)\)表示n不同质因子的个数. 性质1: \(\sum_{d|n}\mu(d)=[n=1]\) 证明:我们把n分解质因数,则原式\(=(-1+1)^{\omega(n)}=0\). 因为对于不同的质因子,只有选和不选两种方案,这是一个组合数相加的形式,偶数加奇数减,根据二项式

莫比乌斯函数与杜教筛

前人的文章已经很详尽了,这里只作一点补充. 莫比乌斯反演与莫比乌斯函数入门资料:https://wenku.baidu.com/view/fbec9c63ba1aa8114431d9ac.html 讲的非常清楚,这里稍微补充一下: 1.虽然考试肯定不会考,但是对于定理的证明还是应该大概了解一下的.关于欧拉函数φ与莫比乌斯函数μ,由于它们都是积性函数,所以很多性质都可以用类似数学归纳法的方法证明.过程是:(1)对于一个性质证明在x为素数是成立 (2)对于素数p和一个正整数a,设此性质对a与p均成立

【bzoj 4176】 Lucas的数论 莫比乌斯反演(杜教筛)

Description 去年的Lucas非常喜欢数论题,但是一年以后的Lucas却不那么喜欢了. 在整理以前的试题时,发现了这样一道题目“求Sigma(f(i)),其中1<=i<=N”,其中 表示i的约数个数.他现在长大了,题目也变难了. 求如下表达式的值: 一行一个整数ans,表示答案模1000000007的值. Sample Input 2 Sample Output 8 HINT 对于100%的数据n <= 10^9. 题解: 解锁新技能:杜教筛. 再复习一下: 若$F(n)=\s

【51nod-1239&amp;1244】欧拉函数之和&amp;莫比乌斯函数之和 杜教筛

题目链接: 1239:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1239 1244:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1244 杜教筛裸题,不过现在我也只会筛这俩前缀和... $$s(n)=\sum _{i=1}^{n}f(i)$$ 那么就有: $$\sum_{i=1}^{n}f(i)\lfloor \frac{n}{i} \

杜教筛 学习总结

看了看唐老师的blog,照猫画虎的做了几道题目,感觉对杜教筛有些感觉了 但是稍微有一点难度的题目还是做不出来,放假的时候争取都A掉(挖坑ing) 这篇文章以后等我A掉那些题目之后再UPD上去就好啦 由于懒得去写怎么用编辑器写公式,所以公式就准备直接copy唐老师的啦 首先积性函数和完全积性函数什么的就不再多说了 列举常见的积性函数: 1.约数个数函数和约数个数和函数 2.欧拉函数phi 3.莫比乌斯函数mu 4.元函数e 其中e(n)=[n==1] 5.恒等函数I 其中I(n)=1 6.单位函数

【BZOJ4916】神犇和蒟蒻 杜教筛

[BZOJ4916]神犇和蒟蒻 Description 很久很久以前,有一只神犇叫yzy; 很久很久之后,有一只蒟蒻叫lty; Input 请你读入一个整数N;1<=N<=1E9,A.B模1E9+7; Output 请你输出一个整数A=\sum_{i=1}^N{\mu (i^2)}; 请你输出一个整数B=\sum_{i=1}^N{\varphi (i^2)}; Sample Input 1 Sample Output 1 1 题解:哎?上面的那个东西好像一直是1?(废话),然后 设j=i/d,

【bzoj4176】Lucas的数论 莫比乌斯反演+杜教筛

题目描述 去年的Lucas非常喜欢数论题,但是一年以后的Lucas却不那么喜欢了. 在整理以前的试题时,发现了这样一道题目“求Sigma(f(i)),其中1<=i<=N”,其中 表示i的约数个数.他现在长大了,题目也变难了. 求如下表达式的值: 其中f(ij)表示ij的约数个数. 他发现答案有点大,只需要输出模1000000007的值. 输入 第一行一个整数n. 输出 一行一个整数ans,表示答案模1000000007的值. 样例输入 2 样例输出 8 题解 莫比乌斯反演+杜教筛 首先有个神奇