zoukankan      html  css  js  c++  java
  • 关于求解某数所有因子欧拉函数的复杂性分析

    【命题】

    对于给定数 (n) ,求解其所有因子的欧拉函数值

    本文不讨论朴素做法,仅讨论两种较为常用的求解方法


    【法一】

    根据公式 (displaystyle oldsymbol varphi(n)=nprod_{i=1}^m (1-{1over p_i})),其中 (displaystyle n=prod_{i=1}^m p_i)

    对于 (n) 的每个因子 (d) ,暴力查询 (sqrt d) 范围内的质因子,并筛除

    最后核验 (d) 是否存在大于 (sqrt d) 的质因子,若存在,则再计算该质因子贡献

    复杂度为 (O(sqrt d))

    int phid=d;
    for(int i=2;i*i<=d;++i) if(d%i==0) {
        while(d%i==0) d/=i;
        phid=phid/i*(i-1);
    }
    if(d>1){
        phid=phid/d*(d-1);
    }
    

    复杂度计算时,考虑 (n) 不大于 (sqrt n) 的因子最多 (sqrt n) 个,故不小于 (sqrt n) 的因子与之成对出现,也不超过 (sqrt n)

    故每当出现 (n) 一个不大于 (sqrt n) 的因子 (d) 时,我们对称考虑与它成对出现的因子 ({nover d})

    (displaystyle quad T(n))

    (displaystyle leqsum_{d=1}^{sqrt n}(sqrt d+sqrt {nover d}))

    (displaystyle =O(int_1^{sqrt n}sqrt x ext dx)+sqrt ncdot O(int_1^{sqrt n}{1over sqrt x} ext dx))

    (displaystyle =O(x^{3over 2}|_1^{sqrt n})+sqrt ncdot O(x^{1over 2}|_1^{sqrt n}))

    (displaystyle =O(n^{3over 4})+O(n^{3over 4}))

    (displaystyle =O(n^{3over 4}))


    【法一优化】

    由于复杂度计算时,不难发现,小于 (sqrt n) 部分的因子和大于 (sqrt n) 部分的因子复杂度贡献均为 (O(n^{3over 4}))

    根据质数定理的推论,(n) 范围内质数个数大约为 ({nover ln n})

    故计算 (n) 的欧拉函数,仅需枚举 (sqrt n) 范围内的质数,复杂度为 (O({sqrt nover lnsqrt n})=O({sqrt nover log n}))

    总求解复杂度如下:

    (displaystyle quad T(n))

    (displaystyle leq sum_{d=1}^{sqrt n}({sqrt dover ln sqrt d}+{sqrt{nover d}over ln sqrt{nover d}}))

    (displaystyle =O(int_1^{sqrt n}{2sqrt xover ln x} ext dx)+O(int_1^{sqrt n}{2sqrt {nover x}over ln {nover x}} ext d{nover x}))

    (displaystyle =2cdot O({1over 3}cdot int_1^{sqrt n} { ext dx^{3over 2}over ln x^{3over 2}}))

    (displaystyle =O(Li(({sqrt n})^{3over 2})))

    (displaystyle =O(Li(n^{3over 4})))

    由于 (displaystyle lim_{n o +infty} {Li(n)over ({nover ln n})}=1)

    (displaystyle T(n)=O({n^{3over 4}over ln n^{3over 4}})=O({n^{3over 4}over log n}))

    若额外考虑打出 (m) 范围内的欧拉函数值,显然 (mleq sqrt n) 时,对渐进复杂度无影响

    (m>sqrt n) 时,第二部分求解 ({nover d}) 时,上界修改为 ({nover m})

    故求解复杂度优化为 (displaystyle O(m+{({nover m})^{3over 2}over log {nover m}})),其中 (O(m)) 为欧拉筛复杂度

    由于欧拉筛往往被视为预处理,当计算上述结果 (k) 次时,每次的均摊复杂度为 (displaystyle O({mover k}+{({nover m})^{3over 2}over log {nover m}}))

    由均值不等式,当且仅当 (displaystyle {mover k}={({nover m})^{3over 2}over log {nover m}}) ,即约为 (m=k^{2over 5}cdot n^{3over 5}) 时取最小

    此时均摊复杂度约为 (displaystyle O({mover k})=O(({nover k})^{3over 5})) 达到最小

    总复杂度约为 (displaystyle kcdot O({mover k})=O(k^{2over 5}cdot n^{3over 5}))

    (k=1) 时取 (m=n^{3over 5}, T(n)approx O(n^{3over 5}))


    【法二】

    考虑 (n) 的不同质因子数目,最坏情况下为 (o(log n))

    (ngeq 2cdot 3cdot 5cdot 7cdots p_m>2cdot 2cdot 2cdot 2cdots 2=2^m o m<log n)

    但均摊意义下,(n) 的不同质因子数目为 (displaystyle {1over n}sum_{i=1}^infty lfloor{nover p_i} floor)

    由埃氏筛的复杂性可得,均摊意义下,不同质因子数目为 (O(log log n))

    由于枚举 (n) 的所有因子时,其不同质因子均为 (n) 的不同质因子

    故考虑先打出 (n) 的所有不同质因子,方法如上,复杂度为 (O(sqrt n))(O({sqrt nover log n}))

    后续枚举 (n) 的因子时,同样成对枚举,并只使用该 (o(log n)) 数量级的不同质因子去通过公式 (displaystyle oldsymbol varphi(n)=nprod_{i=1}^m (1-{1over p_i})) 计算欧拉函数值

    该部分复杂度为 (O(sqrt n)cdot o(log n)=o(sqrt nlog n))

    总复杂度为 (O(sqrt n)+o(sqrt nlog n)=o(sqrt nlog n))(O({sqrt nover log n})+o(sqrt nlog n)=o(sqrt nlog n))

    同理,均摊意义下为 (O(sqrt nloglog n))

    vector<int> divi;
    inline void divit(int n){
        divi.clear();
        for(int i=2, I=sqrt(n)+1e-6;i<=I;++i) if(n%i==0) {
            while(n%i==0) n/=i;
            divi.push_back(i);
        }
        if(n>1)
            divi.push_back(n);
    }
    inline int phi(int n){
        int res=n;
        for(auto p : divi)
            if(n%p==0)
                res=res/p*(p-1);
        return res;
    }
    

    【总结】

    关于法二与法一的复杂度比较,这里给出计算:

    1. 对于未优化的法一,若法二更优,则 (sqrt nlog nleq n^{3over 4}),得出 (log nleq n^{1over 4})

    由牛顿迭代计算得 (ngeq 5503.6646890767315) 。故在复杂度允许范围内,法二是普遍更优的

    1. 对于预处理质数的法一,若法二更优,则 (sqrt nlog nleq {n^{3over 4}over log n}),得出 (log nleq n^{1over 8})

    由牛顿迭代计算得 (ngeq 214910065295.76816approx 2^{31}) 。故在 int 范围内,预处理质数的法一更优;int 边界时,两者复杂度相差较小;int 范围以外,法二更优

    1. 对于预处理欧拉函数的法一,考虑 (k) 远小于 (n) 时,若法二更优,则 (sqrt nlog nleq n^{3over 5}),得出 (log nleq n^{1over 10})

    由牛顿迭代计算得 (ngeq 3430631121407792.0approx 3.4 imes 10^{15}) 。故在复杂度允许的范围内,预处理欧拉函数的法一是普遍更优的

    1. 对于均摊意义下的法二与预处理欧拉函数的法一,考虑 (k) 远小于 (n) 时,若法二更优,则 (sqrt nloglog n leq n^{3over 5}),得出 (log log nleq n^{1over 10})

    这个等式是恒成立的。故在均摊意义下,法二快于法一。


    【附录】

    给出 (n) 以内不同质因子个数 (m) 的范围:

    (n) (10^1) (10^2) (10^3) (10^4) (10^5) (10^6) (10^7) (10^8) (10^9) (10^{10}) (10^{11}) (10^{12}) (10^{13}) (10^{14}) (10^{15}) (10^{16}) (10^{17}) (10^{18}) (10^{19})
    (m) (2) (3) (4) (5) (6) (7) (8) (8) (9) (10) (10) (11) (12) (12) (13) (13) (14) (15) (15)

    可以发现,在复杂度允许范围内,答案与 (lg n) 较为接近

  • 相关阅读:
    4. Postman测试集的批量执行(转)
    3. Postman Tests断言(转)
    2. Postman发送各种格式请求的方法
    1. Postman的安装
    2. Django创建项目
    Redis学习笔记(一)
    Oracle连接查询
    Redis学习笔记(五)- 数据类型之set类型
    Redis学习笔记(四)-数据类型之list类型
    PL/SQL实现JAVA中的split()方法的小例子
  • 原文地址:https://www.cnblogs.com/JustinRochester/p/15059088.html
Copyright © 2011-2022 走看看