• 约数个数与约数和专题


    一、约数个数公式

    如果\(n\)的唯一分解式: \(n={p_1}^{r_1} {p_2}^{r_2} ... {p_k}^{r_k}\)

    一、\(n\)的约数个数公式:

    $d(n) = (r_1+1) * (r_2+1) * ... * (r_k+1) $

    证明:以\(p_1\)为例,这个质数因子,可以选择\(0\)个,可以选择\(1\)个,...,最多可以选择\(r_1\)个,就是有\(r_1+1\)种选择的可能性,其它\(p_2,p_3,...,p_k\)都是如此,根据乘法原理,所有的可能性就是\((r_1+1) * (r_2+1) * ... * (r_k+1)\)

    举个栗子:
    \(180= 2^2 * 3^2 * 5\)

    约数个数\(=(1+2) * (1+2) * (1+1) =18\)

    二、求单个数字的约数个数

    #include <bits/stdc++.h>
    
    using namespace std;
    typedef long long LL;
    
    /**
     * 功能:计算约数个数
     * @param n
     * @return
     */
    LL getDivisorCount(LL x) {
        unordered_map<int, int> primes; //key:质数 value:个数
        //求质数因子
        for (int i = 2; i <= x / i; i++)
            while (x % i == 0) x /= i, primes[i]++; //primes[i]表示质数i因子的个数+1
    
        //如果还有质数,那就加上
        if (x > 1) primes[x]++;
        //公式大法
        LL res = 1;
        for (auto p: primes) res = res * (p.second + 1);
        return res;
    }
    
    LL res;
    
    int main() {
        int n;
        cin >> n;
        for (int i = 1; i <= n; i++) cout << i << " " << getDivisorCount(i) << endl;
        return 0;
    }
    

    三、求数字连乘积的约数个数

    #include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long LL;
    typedef pair<int, int> PII;
    const int N = 110;
    const int mod = 1e9 + 7;
    //记录质数因子及个数
    unordered_map<int, int> primes;
    int n;
    
    int main() {
        cin >> n;
        while (n--) {
            int x;
            cin >> x;
            for (int i = 2; i <= x / i; i++)
                while (x % i == 0) {
                    x /= i;
                    primes[i]++;
                }
            //如果还有大因子,那就加上
            if (x > 1) primes[x]++;
        }
        //公式
        LL res = 1;
        for (PII p: primes) res = res * (p.second + 1) % mod;
        //输出结果
        cout << res << endl;
        return 0;
    }
    

    四、约数和公式

    如果\(n\)的唯一分解式: \(n={p_1}^{r_1} {p_2}^{r_2} ... {p_k}^{r_k}\)

    约数和:

    $\sigma(n)=({p_1}^{0}+{p_1}^{1}+{p_1}^{2}+...+{p_1}^{r_1})({p_2}^{0}+{p_2}^{1}+{p_2}^{2}+...+{p_2}^{r_2})...({p_k}^{0}+{p_k}^{1}+{p_k}^{2}+...+{p_k}^{r_k}) $

    Sigma(大写Σ,小写σ),是第十八个希腊字母。

    举个栗子:
    \(180= 2^2 * 3^2 * 5\)

    约数和\(=(1+2+4) * (1+3+9 ) * (1+5)=546\)

    五、求单个数字的约数和

    #include <bits/stdc++.h>
    
    using namespace std;
    typedef long long LL;
    
    /**
     * 功能:计算约数之和
     * @param n
     * @return
     */
    LL getSumOfDivisors(LL x) {
        //拆出所有质数因子及质数因子个数
        unordered_map<int, int> primes;
        for (int i = 2; i <= x / i; i++)
            while (x % i == 0) {
                x /= i;
                primes[i]++;
            }
        if (x > 1) primes[x]++;
    
        //计算约数个数
        LL res = 1;
        for (auto p : primes) {
            LL a = p.first, b = p.second;
            LL t = 1;
            while (b--) t = (t * a + 1);
            res = res * t;
        }
        return res;
    }
    
    LL res;
    
    int main() {
        //测试用例:180
        //参考答案:546
        int n;
        cin >> n;
        cout<<getSumOfDivisors(n) << endl;
        return 0;
    }
    

    六、筛法求区间约数个数和约数和

    #include <bits/stdc++.h>
    
    using namespace std;
    typedef long long LL;
    
    /**
     * 功能:线性筛出约数个数与约数和
     * Tag:模板,约数个数,约数和
     */
    const int N = 1e6 + 10;
    int n;
    int primes[N];      //质数数组
    int idx;            //质数数组下标游标
    bool st[N];         //是否已被筛出
    int d[N];           //约数个数数组
    int sigma[N];       //约数和数组
    
    void get_divisor(int n) {
        //积性函数的出发值
        d[1] = sigma[1] = 1;
    
        for (int i = 2; i <= n; i++) {  //倍数
            if (!st[i])primes[++idx] = i, d[i] = 2, sigma[i] = i + 1;
            for (int j = 1; i * primes[j] <= n & j <= idx; j++) {
                st[i * primes[j]] = true;
                d[i * primes[j]] = d[i] << 1;
                sigma[i * primes[j]] = sigma[i] * (primes[j] + 1);
                if (i % primes[j] == 0) {
                    d[i * primes[j]] -= d[i / primes[j]];
                    sigma[i * primes[j]] -= primes[j] * sigma[i / primes[j]];
                    break;
                }
            }
        }
    }
    
    LL res;
    
    int main() {
        cin >> n;
        //开始筛约数个数,约数和
        get_divisor(n);
        //输出约数个数和
        for (int i = 1; i <= n; i++) res += d[i];
        cout << res << endl;
        return 0;
    }
    
  • 相关阅读:
    采用商业智能提升企业的数字营销策略
    采用商业智能提升企业的数字营销策略
    《PostgreSQL服务器编程》一一1.3 超越简单函数
    《PostgreSQL服务器编程》一一1.3 超越简单函数
    《PostgreSQL服务器编程》一一1.3 超越简单函数
    《PostgreSQL服务器编程》一一1.3 超越简单函数
    2017 全球半导体预估跳增 11.5%,存储器最夯
    2017 全球半导体预估跳增 11.5%,存储器最夯
    如何从零学习PostgreSQL Page结构
    转成json必须是unicdoe字符
  • 原文地址:https://www.cnblogs.com/littlehb/p/15214618.html
Copyright © 2020-2023  润新知