Solution -「HDU」Professor Ben

Description

\(Q\) 个询问。每次给定一个正整数 \(n\),求它的所有因数的质因数个数的和。


Solution

就讲中间的一个 Trick。

我们定义正整数 \(x\)\(f(x)\) 个因数,且存在一函数 \(g(x) = \sum_{i | x} f^3(i)\),显然 \(g(x)\)\(x\) 对应的答案。

那么,若 \(x = p^a\),则由因数个数定理可得: \(f(x) = a + 1\)

且其因数集合可表示为:\(\{p^0, p^1, ... , p^a\}\)。故有 \(g(x) = \sum_{i = 0}^{a} f^3(p^i) = \sum_{i = 0}^{a} (i + 1)^3\)

\(x\) 的范围加以推广。

\(x = p^a q^b\),则 \(f(x) = (a + 1) \times (b + 1)\)

且其因数集合可表示为:\(\{\{p^0 q^0, p^0 q^1, ..., p^0 q^b\}, \{p^1 q^0, p^1 q^1, ..., p^1 q^b\}, ... , \{p^a q^0, p^a q^1, ..., p^a q^b\}\}\)。故有 \(g(x) = \sum_{i = 0}^{a}\sum_{j = 0}^{b} f^3(p^i q^j) = \sum_{i = 0}^{a}\sum_{j = 0}^{b} (i + 1)^3 (j + 1)^3\)

注意到 \(g(p^a) = \sum_{i = 0}^{a} (i + 1)^3, g(q^b) = \sum_{j = 0}^{b} (j + 1)^3\)

所以有 \(g(x) = g(p^a q^b) = g(p^a) \times g(q^b)\)。显然可推广至结论:

\[g(x) = g(p_1^{a_1} p_2^{a_2} ... p_k^{a_k}) = \prod_{i = 1}^{k} g(p_i^{a_i}) \]

然后就可以当结论题切掉它。


Code

#include <cstdio>

typedef long long LL;
int Max(int x, int y) { return x > y ? x : y; }
int Min(int x, int y) { return x < y ? x : y; }
int Abs(int x) { return x < 0 ? -x : x; }

int read() {
    int k = 1, x = 0;
    char s = getchar();
    while (s < '0' || s > '9') {
        if (s == '-')
            k = -1;
        s = getchar();
    }
    while (s >= '0' && s <= '9') {
        x = (x << 3) + (x << 1) + s - '0';
        s = getchar();
    }
    return x * k;
}

void write(LL x) {
    if (x < 0) {
        putchar('-');
        x = -x;
    }
    if (x > 9)
        write(x / 10);
    putchar(x % 10 + '0');
}

void print(LL x, char s) {
    write(x);
    putchar(s);
}

const int MAXN = 5e6 + 5;

bool flag[MAXN];
int num[MAXN], len = 0;
LL w[MAXN];

void Euler(int n) {
    flag[1] = true;
    for (int i = 2; i <= n; i++) {
        if (!flag[i])
            num[++len] = i;
        for (int j = 1; j <= len; j++) {
            if (i * num[j] > n)
                break;
            flag[i * num[j]] = true;
            if (i % num[j] == 0)
                break;
        }
    }
}

int main() {
    Euler(MAXN - 5);
    for (int i = 1; i < 23; i++)
        for (int j = 0; j <= i; j++) w[i] += (1 + j) * (1 + j) * (1 + j);
    int n = read();
    for (int i = 1, x; i <= n; i++) {
        x = read();
        LL res = 1;
        for (int j = 1; num[j] * num[j] <= x; j++) {
            int cnt = 0;
            while (x % num[j] == 0) {
                x /= num[j];
                cnt++;
            }
            res *= w[cnt];
        }
        if (x > 1)
            res *= w[1];
        print(res, '\n');
    }
    return 0;
}
posted @ 2021-08-13 17:36  STrAduts  阅读(81)  评论(2编辑  收藏  举报