zoukankan      html  css  js  c++  java
  • 「数论函数」学习笔记

    定义域为正整数,值域为整数的函数称为数论函数。OI中常用的数论函数有(mu)(varphi)等。

    积性函数

    完全积性函数:(f(ab)=f(a)f(b))

    一般积性函数:(f(ab)=f(a)f(b),a perp b)

    常见的积性函数如下:

    莫比乌斯函数 (mu(n))
    欧拉函数 (varphi(n))
    单位函数 ( ext{id}(n)=n)
    元函数 (epsilon(n)=[n=1])
    恒等函数 (I(n)=1)
    约数个数 $d(n)=sumlimits_{i=1}^n[i
    约数和 $sigma(n)=sumlimits_{i

    狄利克雷卷积

    两个函数(f,g)的狄利克雷卷积(t)

    [t(n)=sumlimits_{d|n}f(d)g(dfrac{n}{d}) ]

    记为(t = f ast g)

    一个重要的性质:两个积性函数的狄利克雷卷积仍为积性函数

    整除分块

    假如说我们要求解$$sumlimits_{i=1}^{n}left lfloor n over i ight floor$$

    直接模拟是(O(n))的。而我们发现(left lfloor dfrac{n}{i} ight floor)(i)相近时会有很多重复的值。整除分块的思想就是将所有重复的数值一起计算

    有结论(left lfloor dfrac{n}{i} ight floor .. left lfloor dfrac{n}{n/(n/i)} ight floor)的值都是相等的,而(left lfloor dfrac{n}{i} ight floor)总共有不超过(2sqrt{n})个取值。因此复杂度是(O(sqrt{n}))

    莫比乌斯函数

    定义

    考虑一个函数(F(n)=sumlimits_{d|n}f(d)),能否通过对(f)进行容斥得出(F)?其容斥系数满足什么特定规律吗?

    我们发现(F)的定义其实是个狄利克雷卷积的形式。即(F=f ast I)

    因此(f)即为(F)卷上“(I)的狄利克雷逆”。由此我们便定义这个容斥系数,也就是莫比乌斯函数(mu),为(I)的逆。即

    [mu ast I = epsilon(n) ]

    [sumlimits_{d|n}mu(d)=[n=1]=epsilon(n) ag{1.1} ]

    莫比乌斯函数的性质

    性质一

    (mu)函数为积性函数。即

    [mu(m ast n) = mu(m) ast mu(n), m perp n ag{1.2} ]

    性质二

    由此任意的莫比乌斯函数都可以表示为(mu(n)=prodlimits_{i} mu(p_i^{y_i})) (分解质因数)

    (p^y)很特殊,根据之前的结论有(sumlimits_{d|p^y}mu(d)=0),因此(mu(1)+mu(p)+mu(p^2)+ cdots mu(p^y)=0)

    由此猜测莫比乌斯函数值的性质:(mu(1)=1,mu(p)=-1),并且对于所有指数(y)大于(1)的,满足(mu(p^y)=0)

    也就是:

    [mu(d) = egin{cases} 1 & d=1 \ (-1)^y & d=p_1 ast p_2 ast cdots ast p_y \ 0 & otherwiseend{cases} ag{1.3} ]

    这个结论是正确的。我们可以用二项式定理证明这样的性质满足莫比乌斯函数的定义:

    (n>1)时,将(n)分解质因数得(n=p_1^{y_1} ast p_2^{y_2} ast ... ast p_k^{y_k})。任何一个质数的个数超过(1)时莫比乌斯函数值一定为(0),可以不管。我们只需要考虑有多少个质因数的指数都为(1)。因此有

    [egin{aligned} & sumlimits_{d|n} mu(d) \ =& sumlimits_{i=0}^{k} C^{i}_{k} ast (-1)^i \ =& sumlimits_{i=0}^{k} dbinom{k}{i} (-1)^i 1^{k-i} \ =& 0 end{aligned} ]

    线性筛

    积性函数都可以由线性筛求得。代码如下:

    inline void SieveMu(int n){
        mu[1] = 1;
        for(int i = 2; i <= n; ++i){
            if(!b[i]){
                prm[++tot] = i;
                mu[i] = -1;
            }
            for(int j = 1; j <= tot && i*prm[j] <= n; ++j){
                b[i*prm[j]] = 1;
                if(i % prm[j] == 0){
                    mu[i*prm[j]] = 0;
                    break;
                }else{
                    mu[i*prm[j]] = -mu[i];
                }
            }
        }
    }
    

    莫比乌斯反演

    根据莫比乌斯函数的定义,我们发现莫比乌斯函数具有如下的反演原理。

    公式 1

    [F(n)=sumlimits_{d|n}f(d) xrightarrow[]{反演} f(n)=sumlimits_{d|n}mu(d)F(dfrac{n}{d}) ag{1.4} ]

    公式 2

    [F(n)=sumlimits_{n|d}f(d) xrightarrow[]{反演} f(n)=sumlimits_{n|d}mu(dfrac{d}{n})F(d) ag{1.5} ]

    问题一

    求$sumlimits_{i=1}^{n}sumlimits_{j=1}^{m }[gcd(i,j) = k], (n < m ) $

    直接通过定义来变形:

    [egin{aligned} &=sumlimits_{i=1}^{n/k}sumlimits_{j=1}^{m/k}[gcd(i,j)=1] \ &=sumlimits_{i=1}^{n/k}sumlimits_{j=1}^{m/k}sumlimits_{d|gcd(i,j)}mu(d) \ &=sumlimits_{d=1}^{n}mu(d)sumlimits_{d|i}^{n/k}sumlimits_{d|j}^{m/k}1\ &=sumlimits_{d=1}^{n}mu(d)sumlimits_{i=1}^{left lfloor frac{n}{kd} ight floor}sumlimits_{j=1}^{left lfloor frac{m}{kd} ight floor} 1\ &= sumlimits_{d=1}^{n}mu(d)left lfloor frac{n}{kd} ight floorleft lfloor frac{m}{kd} ight floor\ end{aligned} ]

    可以使用整除分块(O(sqrt{n}))求解。

    (gcd)换到外面枚举是一个常用的(trick)

    问题二

    (sumlimits_{i=1}^{n}sumlimits_{j=1}^{m}gcd(i,j),(n<m))

    [egin{aligned} &= sumlimits_{d=1}^{n}dsumlimits_{i=1}^{n} sumlimits_{j=1}^{m}[gcd(i,j)=d] \ &=sumlimits_{d=1}^{n}dsumlimits_{i=1}^{n/d}mu(i)left lfloor dfrac{n}{i d} ight floor left lfloor dfrac{m}{id} ight floor \ end{aligned} ]

    第一个(sum)可以用整除分块,第二个也是。于是复杂度为(O(n))

    我们还可以进一步优化——设(T=i cdot d),则有

    [egin{aligned} &=sumlimits_{d=1}^{n}dsumlimits_{i=1}^{left lfloor frac{n}{d} ight floor}mu(dfrac{T}{d})left lfloor dfrac{n}{T} ight floor cdot left lfloor dfrac{m}{T} ight floor \ &=sumlimits_{T=1}^{n}left lfloor dfrac{n}{T} ight floor left lfloor dfrac{m}{T} ight floorsumlimits_{d|T}dmu(dfrac{T}{d}) end{aligned} ]

    后面部分(sumlimits_{d|T}dmu(dfrac{T}{d}))是一个狄利克雷卷积,是一个积性函数,我们可以在线性筛时筛出。然后直接整除分块就可以(O(sqrt{n}))完成求解了。

    将两个数的乘积设做一个变量进行恒等变形也是一个常用(trick)

    欧拉函数

    定义

    对于一个正整数(n),小于(n)且与(n)互质的正整数个数记作(varphi(n))

    [varphi(n) = sumlimits_{i=1}^{n-1}[gcd(n,i)=1] ag{2.1} ]

    其中特殊定义(varphi(1)=1)

    常用的欧拉函数值:(varphi(p)=p-1, varphi(p^k)=p^k-p^{k-1})

    其中,欧拉函数也是积性函数。满足(varphi(nm)=varphi(n)varphi(m), n perp m),因此也可以通过线性筛求出。

    既然这样,那么将(n)分解质因数得到(n=prodlimits_{i}p_{i}^{k_i}),则有(varphi(n)=prodlimits_{i}varphi(p_i^{k_i}))

    于是就得出了(varphi)的通项公式:

    [varphi(n)=prodlimits_{i}(p_i^{k_i}-p_i^{k_i-1})=n prodlimits_{i}(1-{1 over p_i}) ag{2.2} ]

    欧拉函数的性质

    [sumlimits_{d|n}varphi(d)=n ag{2.4} ]

    这个性质非常巧妙。这其实是一个真分数约分的过程。

    [frac{0}{12},frac{1}{12},frac{2}{12},frac{3}{12},frac{4}{12},frac{5}{12},frac{6}{12},frac{7}{12},frac{8}{12},frac{9}{12},frac{10}{12},frac{11}{12} ]

    约分后交换顺序得到

    [frac{0}{1},frac{1}{2},frac{1}{3},frac{2}{3},frac{1}{4},frac{3}{4},frac{1}{6},frac{5}{6},frac{1}{12},frac{5}{12},frac{7}{12},frac{11}{12} ]

    当然这个性质可以表示成狄利克雷卷积的形式:

    [sumlimits_{d|n}varphi(d)I(dfrac{n}{d})=n ]

    也就是

    [varphi ast I = ext{id} ]

    那么也就得到了

    [varphi = mu ast ext{id} ag{2.5} ]

    [varphi(n) = sumlimits_{d|n}mu(d) dfrac{n}{d} Leftrightarrow dfrac{varphi(n)}{n} = sumlimits_{d|n}dfrac{mu(d)}{d} ag{2.6} ]


    杜教筛

    杜教筛要解决的问题时在低于线性的复杂度下求出积性函数的前缀和。

    即求

    [S(n)=sumlimits_{i=1}^{n}f(i) ]

    我们找另一个积性函数(g)去卷(f),令(h = f ast g)

    那么

    [egin{aligned} sumlimits_{i=1}^{n}h(i) &=sumlimits_{i=1}^{n}(f*g)(i) \ &=sumlimits_{i=1}^{n}sumlimits_{d|i}^{i}g(d)f(dfrac{i}{d}) \ &=sumlimits_{d=1}^{n}g(d)sumlimits_{d|i}^{n}f(dfrac{i}{d}) \ &=sumlimits_{d=1}^{n}g(d)sumlimits_{i=1}^{left lfloor frac{n}{d} ight floor}f(i) \ &= sumlimits_{d=1}^{n}g(d)S(left lfloor frac{n}{d} ight floor) \ end{aligned} ]

    我们要求的是(S(n)),因此考虑将它表示出来:

    [sumlimits_{i=1}^{n}h(i) = g(1)S(n)+sumlimits_{d=2}^{n}g(d)S(left lfloor frac{n}{d} ight floor) ]

    移项得到

    [g(1)S(n) = sumlimits_{i=1}^{n}(f*g)(i) -sumlimits_{d=2}^{n}g(d)S(left lfloor frac{n}{d} ight floor) ag{3.1} ]

    这就是杜教筛的核心式子。这是一个递归式,如果我们能够快速求得(f ast g)以及(g)这两个函数的前缀和,那么就可以(O(n^{frac{2}{3}}))求出(S(n))。而难点就在于找出合适的(g)

    问题一

    求出(S(n)=sumlimits_{i=1}^{n}mu(i))

    关于(mu)的卷积,有(mu ast I = epsilon)(epsilon)(I)的前缀和都非常好求,因此我们选择(I)来作为(g)

    根据((3.1))可得

    [1 cdot S(n)=sumlimits_{i=1}^{n}epsilon(i) -sumlimits_{d=2}^{n}1 cdot S(left lfloor frac{n}{d} ight floor) ]

    化简得

    [S(n)=1-sumlimits_{d=2}^{n}S(left lfloor frac{n}{d} ight floor) ag{3.2} ]

    问题二

    求出(S(n)=sumlimits_{i=1}^{n}varphi(i))

    欧拉函数有性质((2.4):)(varphi ast I = ext{id})。因而还是选择(I)来作为(g)

    同理,根据((3.1))

    [1 cdot S(n)=sumlimits_{i=1}^{n} ext{id}(i) -sumlimits_{d=2}^{n}1 cdot S(left lfloor frac{n}{d} ight floor)]

    化简得

    [S(n)=dfrac{n(n+1)}{2}-sumlimits_{d=2}^{n}S(left lfloor frac{n}{d} ight floor) ag{3.3} ]

    代码实现

    这个递归式我们通过记忆化搜索来实现。通过map来储存筛过的值。

    为了提高效率,可以先用欧拉筛筛出(sqrt{n})以内的前缀和,防止杜教筛在小数据范围内递归次数太多。后面部分通过整除分块来实现。

    int DuJiaoMu(int n){
        if(n <= B) return smu[n];
        if(mp_mu[n]) return mp_mu[n];
        int res = 1;
        for(int i = 2,j; i <= n; i = j+1){
            j = n/(n/i);
            res -= (j-i+1)*DuJiaoMu(n/i);
        }
        return mp_mu[n] = res;
    }
    
  • 相关阅读:
    十、Compose命令
    九、compose入门
    JS数组中,两两比较的算法,为了获取重复的值,并在php数组中,使用这种倒三角算法
    题目重复度检测---四种相似度检测的方案+PHP改进计算字符串相似度的函数similar_text()、levenshtein()
    js让文字一个个出现
    客户总想让页面炫酷起来-----怎么炫酷呢?---使用css3的东西或者其animate.css
    关于git的总结:git知识大全,命令行操作,vscode操作
    defer和async的区别
    dom和bom的区别,以及三类偏移属性(JS运动方法中,经常会涉及到这些位置信息)
    认真的对待flex,Flex模型和Flex属性思维导图,以及自己的记忆方法--jaf和aof
  • 原文地址:https://www.cnblogs.com/qixingzhi/p/11137551.html
Copyright © 2011-2022 走看看