acwing算法基础课/算法竞赛进阶指南 约数

首先考虑分解质因数的算法:
在枚举因子时,不停将x除以i直到x不是i的倍数,这样每枚举到一个合数i,x中所有i的因子都已经被除掉了,i不可能成为x的因子。
这样,保证了满足第六行x%i==0的i一定是质因数,顺便统计出了每个质因数的指数。
有一个显然的结论:x中至多有一个大于\(\sqrt{x}\)的质因子,而且它的次数一定是1。(反证即可)
所以可以只循环到i <= x/i,如果退出循环后x>1,特判x是原数的一次质因子即可。
我们记每个质因子是\(p_{i}\),次数是\(c_{i}\)
由乘法原理易得:
由于每个质因子的次数可以选\(0\)\(c_{i}\),故约数的个数是

\[\prod_{i=1}^{n} \left ( c_{i}+1 \right ) \]

考虑每个约数可以选每个质因数的\(0\)\(c_{i}\)次方相乘,所有约数的和为

\[\prod_{i=1}^n (\sum_{j=0}^{c_{i}}p_i^j) \]

  1. 分解质因数
#include <iostream>
using namespace std;

void solve(int x) {
    for (int i = 2; i <= x / i; i++) {
        if (x % i == 0) {
            int p = 0;
            while (x % i == 0) {
                x /= i;
                p++;
            }
            printf("%d %d\n", i, p);
        } 
    }
    if (x > 1) printf("%d 1\n", x);
    printf("\n");
}

int main() {
    int T, x;
    scanf("%d", &T);
    while (T--) {
        scanf("%d", &x);
        solve(x);
    }
    return 0;
}
  1. 约数个数
#include <iostream>
#include <unordered_map>
using namespace std;

const int mod = 1e9 + 7;

int main() {
    unordered_map<int, int> hash;
    int n, x;
    scanf("%d", &n);
    while (n--) {
        scanf("%d", &x);
        for (int i = 2; i <= x / i; i++) {
            while (x % i == 0) {
                x /= i;
                hash[i]++;
            }
        }
        if (x > 1) hash[x]++;
    }

    long long ans = 1;
    for (auto u : hash) ans = ans * (u.second + 1) % mod;
    printf("%lld", ans);
    return 0;
}
  1. 约数之和
#include <iostream>
#include <unordered_map>
using namespace std;

const int mod = 1e9 + 7;

int main() {
    unordered_map <int, int> hash;
    int n, x;
    scanf("%d", &n);
    while (n--) {
        scanf("%d", &x);
        for (int i = 2; i <= x / i; i++) {
            while (x % i == 0) {
                x /= i;
                hash[i]++;
            }
        }
        if (x > 1) hash[x]++;
    }

    long long ans = 1;
    for (auto u : hash) {
        long long t = 1, sum = 1;
        for (int i = 1; i <= u.second; i++) {
            t = t * u.first % mod;
            sum = (sum + t) % mod;
        }
        ans = ans * sum % mod;
    }
    printf("%lld", ans);
    
    return 0;
}
posted @ 2021-11-10 18:06  _vv123  阅读(117)  评论(0编辑  收藏  举报