首页 > 其他 > 详细

线性筛与莫比乌斯反演

时间:2018-01-23 22:53:40      阅读:372      评论:0      收藏:0      [点我收藏+]

线性筛与莫比乌斯反演

和上篇文章一样,一直没有研究这个东西,结果又考了GG……TAT
下定决心学一学,搞好这个东西。

线性筛

筛质数有很多方法,好像很厉害的有洲阁筛、杜教筛(然而我都不会QAQ),比较坑的有暴力筛(就是枚举一个数的倍数)。
我只学了比较简单而且实用的线性筛法。
这种筛法是避免一个数被重复筛几遍,所以效率均摊下来可以达到线性。(网上有证明)

先上代码:

const int N = 100000;
bool is_prime[N+100];
int prime[N], cnt = 0;
void find_prime() {
    Set(is_prime, true);
    is_prime[0] = is_prime[1] = false;
    For(i, 2, N) {
        if (is_prime[i]) 
            prime[++cnt] = i;
        For(j, 1, cnt) {
            if (i * prime[j] > N) break;
            is_prime[i * prime[j] ] = false;
            if (i % prime[j] == 0) break; //here
        }
    }
}

这个代码有一个关键点 就是上面的\(here\) 这个意义就是
对于一个合数\(m\)可以分解为\(m=p_1^{r_1}*...*p_n^{r_n}\)其中
\(p_i\)为质数,那么我们筛\(m\)的时候之前把\(p_1\)筛掉了,所以在
枚举\(i\)的时候。

  1. 如果\(i\)为素数没问题,直接向后继续推(因为筛出的
    质数都类似\(m=p_1*p_2\)的形式,所以不可能重复)。

  2. 如果为合数,那么\(i\)可以分解成\(i=p_1^{r_1}*...*p_n^{r_n}\)形式
    其中\(p_1-p_n\)是递增的,那么\(p_1\)是最小的那个质数。\(i \bmod p_1 = 0\)的时候,就不用继续枚举了,
    所以我们就只能筛出不大于\(p_1\)的质数\(*i\)

莫比乌斯反演

莫比乌斯反演很多时候都能大大简化运算……

  • 定理:\(F(n)\)\(f(n)\)是定义在非负整数集合上的两个
    函数,并且满足条件\(F(n)=\sum \limits \limits _{d|n}{f(d)}\)。那么我们
    就能得到结论:

\(f(n)=\sum \limits \limits _{d|n}\mu(d)F(\frac{n}{d})\)


在上面的公式中有一个\(\mu(d)\)函数,它的定义如下:

(1)若\(d=1\),那么\(\mu(d)=1\)

(2)若\(d=p_1p_2...p_k\)\(p_i\)均为互异质数,
那么\(\mu(d)=(-1)^{k}\)。这个我的理解就是\(d\)
质因数个数为偶数的话,那么\(\mu(d)=1\)否则为\(-1\)

(3)其他情况下\(\mu(d)=0\)这个就是对上面那条的拓展了,
就是指的\(d\)没有一个平方因子,或者说没有一个质因子的
次数大于\(1\)

线性筛求莫比乌斯函数的代码:

const int N = 100100;
bool is_prime[N+100];
int mu[N+100] = {0, 1}, cnt = 0, prime[N+100];
void init() {
    Set(is_prime, true);
    is_prime[1] = false;
    For (i, 2, N) {
        if (is_prime[i]) {
            prime[++cnt] = i;
            mu[i] = -1; //质数的质因子个数肯定为奇数个就是1
        }
        For (j, 1, cnt) {
            if (i * prime[j] > N) break;
            is_prime[i * prime[j] ] = false;
            if (i % prime[j]) mu[i * prime[j] ] = -mu[i]; //多了一个质因子直接变为原来结果的相反数
            else {
                mu[i * prime[j]] = 0; //这个将要被筛的数至少具有两个prime[j]的因子
                break;
            }
        }
    }
}

有了上面的知识,现在,我们来证明莫比乌斯反演定理。

证明:

\(\sum \limits _{d|n}\mu(d)F(\frac{n}{d})=\sum \limits_{d|n}\mu(d)\sum \limits_{d‘|\frac{n}{d}}f(d‘) =\sum \limits \limits _{d‘|n}f(d‘)\sum \limits_{d|\frac{n}{d‘}}\mu(d)=f(n)\)


Q.E.D

  • 然后还要提一下的就是一些常见的定理,证明嘛……
  • 一般都是先分解质因数,然后再根据组合数性质去算,比如第一个。
  • 要么就是对于一些常见的反演格式进行反演,比如第二个。

  • \(\sum \limits _{d|n} \mu(d)=[n=1]\)
  • \(\sum \limits _{d|n} \frac{\mu(d)}{d}=\frac{\varphi(n)}{n}\)


一些例题(难题)

\(\sum \limits \limits _{i=1}^{n} \sum \limits_{i=1}^{m} lcm(i,j)\)

\(=\sum \limits \limits _{i=1}^{n} \sum \limits_{i=1}^{m} \frac{i\ j}{gcd(i,j)}\)

\(=\sum \limits \limits _{d=1}^{min(n,m)} \ d \sum \limits_{i=1}^{\lfloor \frac{n}{d} \rfloor} \sum \limits_{j=1}^{\lfloor \frac{m}{d} \rfloor} \ ij \ [gcd(i,j)=1]\)

这个就是一个更换枚举相的操作了,是个套路。
你先枚举所有可能的\(gcd\)再计算这种\(gcd\)的贡献。

比如前面的那个\(d\)就是我们枚举的\(gcd\),后面所有可能的数对,就是在\(\lfloor \frac{n}{d} \rfloor\)\(\lfloor \frac{m}{d} \rfloor\)中的所有互质的数对的乘积在乘上\(d\)

这个可以简单理解一下,就是两个数分别除以他们的最大公因数,然后两个数肯定是互质的。
但其对于答案的贡献就多除以了一个\(d\),所以要乘回来。

\(ans =\sum \limits _{d=1}^{min(n,m)} \ d \sum \limits_{i=1}^{\lfloor \frac{n}{d} \rfloor} \sum \limits_{j=1}^{\lfloor \frac{m}{d} \rfloor} \sum \limits_{x|gcd(i,j)}\mu(x) * i * j\)

这个就是运用了前面的公式\(\sum \limits _{d|n} \mu(d)=[n=1]\)来替代了\([gcd(i,j)=1]\)的条件。(这个就是套路了)

然后我们继续推:

\(ans =\sum \limits \limits _{d=1}^{min(n,m)} d \sum \limits_{x=1}^{min(\lfloor \frac{n}{d} \rfloor,\lfloor \frac{m}{d} \rfloor)} \mu(x) \ x^2 \sum \limits_{i=1}^{\lfloor \frac{n}{dx} \rfloor} i \sum \limits_{j=1}^{\lfloor \frac{m}{dx} \rfloor} j\)

这个也是套路,把\(x\)提前了。就是改成了枚举\(x\)看看它的对于答案的贡献是多少。
很容易发现,就是在\([1,\lfloor \frac{n}{dx} \rfloor]\)中的所有数乘上\(x\)
就是原来可行的\(i\)。然后我们就可以根据这个来优化了。

前面那两个\(\sum \limits\)就是\(n \ ln \ n\)(令\(n=max(n,m)\))的复杂度。(就是\(\sum \limits \limits _{i=1}^{n} \frac{n}{i}\))。后面的那两个,直接用等差数列求和公式\(O(1)\)算。

但这个仍然过不去...(\(O(1.61*10^8)\),$ % $的常数还很大)所以就需要来用套路的整除分块了。
就是把后面两个 \(\sum \limits\) 很多一样答案的地方一起处理掉,所以对于那个 \(\mu(x) \ x^2\) 还要记一个前缀和。

总复杂度\(O(\sum \limits _{i=1}^{n} \sqrt{\frac{n}{i}})=O(pass)\)这个我也不会算。。大佬说似乎是\(O(n^{\frac{2}{3}})\)

线性筛与莫比乌斯反演

原文:https://www.cnblogs.com/zjp-shadow/p/8338033.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!