1. 程式人生 > >[HDU5382]GCD?LCM!

[HDU5382]GCD?LCM!

.cn otp nlog mbo n) problem splay break rac

Description

HDU5382
會嗎?不會!
\(F(n)=\sum\limits_{i = 1}^{n}\sum\limits_{j=1}^{n}[lcm(i,j)+gcd(i,j)\ge n]\),求\(S(n)=\sum\limits_{i=1}^{n}F(n)\)

Soluiton

\[ F(n) = n^2 - \sum\limits_{i = 1}^{n}\sum\limits_{j=1}^{n}[lcm(i,j)+gcd(i,j) < n]\F(n) - F(n-1) = n^2 - \sum\limits_{i = 1}^{n}\sum\limits_{j=1}^{n}[lcm(i,j)+gcd(i,j) < n] - (n-1)^2 - \sum\limits_{i = 1}^{n-1}\sum\limits_{j=1}^{n-1}[lcm(i,j)+gcd(i,j) < n-1]\= 2n - 1 - \sum\limits_{i = 1}^{n}\sum\limits_{j=1}^{n}[lcm(i,j)+gcd(i,j) = n]\F(n) = F(n-1) + (2n-1) - \sum\limits_{i = 1}^{n}\sum\limits_{j=1}^{n}[lcm(i,j)+gcd(i,j) = n] \]



\[ G(n) = \sum\limits_{i = 1}^{n}\sum\limits_{j=1}^{n}[lcm(i,j)+gcd(i,j) = n]\= \sum\limits_{i = 1}^{n}\sum\limits_{j=1}^{n}[\dfrac{k_igcd(i,j)\cdot k_j gcd(i,j)}{gcd(i,j)}+gcd(i,j) = n]\= \sum\limits_{d=1}^{n}\sum\limits_{i=1}^{\lfloor \dfrac{n}{d} \rfloor}\sum\limits_{j=1}^{\lfloor \dfrac{n}{d} \rfloor}[ijd + d = n][gcd(i,j) = 1]\= \sum\limits_{d|n}\sum\limits_{i=1}^{\dfrac{n}{d}}\sum\limits_{j=1}^{\dfrac{n}{d}}[(ij) = \dfrac{n}{d} - 1][gcd(i,j) = 1]\\]


\[ H(n) = \sum\limits_{i=1}^{n+1}\sum\limits_{j=1}^{n+1}[ij = n][gcd(i,j) = 1]\= \sum\limits_{i=1} [gcd(i, \dfrac{n}{i}) = 1] \]

\[ G(n) = \sum\limits_{d|n} H(\dfrac{n}{d} - 1) \]
不難想到,將\(n\)質因數分解後,\(p_x^{a_x}\)要麽在\(i\)那一部分,要麽在\(\dfrac{n}{i}\)那一部分,所以
\[ H(n) = 2^k (k \mbox{ is the number of prime factors of }n) \]

所以\(H(n)\) 是一個積性函數,可以歐拉篩。然後在計算每個\(H\)\(G\)的貢獻,這樣復雜度是\(O(nlogn)\)的,然後就能\(O(n)\)的求出\(F\)\(S\)

綜上,這個題不涉及NOIp以外的知識,NOIp可以考這麽難的

Code

#include <bits/stdc++.h>

typedef long long LL;
const int N = 1e6 + 10;
const LL MOD = 258280327;

LL F[N], G[N], H[N], S[N];
int notp[N], pri[N], cnt;

int get_prime() {
    for (int i = 1; i < N; ++i) H[i] = 1;
    for (int i = 2; i < N; ++i) {
        if (!notp[i]) {
            pri[cnt++] = i;
            H[i] = 2;
        }
        for (int j = 0; j < cnt; ++j) {
            int k = i * pri[j];
            if (k >= N) break;
            notp[k] = 1;
            if (i % pri[j] == 0) {
                (H[k] *= H[i]) %= MOD;
                break;
            }
            else {
                (H[k] *= 2 * H[i] % MOD) %= MOD;
            }
        }
    }
    for (int i = 1; i < N; ++i) {
        for (int j = i; j < N; j += i) {
            G[j] = (G[j] + H[j/i - 1]) % MOD;
        }
    }
    F[1] = 1;
    for (int i = 2; i < N; ++i) {
        F[i] = ((LL)F[i-1] + i + i - 1LL - G[i-1]) % MOD;
    }
    for (int i = 1; i < N; ++i) {
        S[i] = (S[i-1] + F[i]) % MOD;
    }
}

int main() {
    get_prime();
    int t;
    scanf("%d", &t);
    while (t--) {
        int n;
        scanf("%d", &n);
        printf("%d\n", S[n]);
    }
    return 0;
}

[HDU5382]GCD?LCM!