"CF235E" Number Challenge "Mobius inversion"

:( to a conclusion from the two-dimensional extension, is also a three-dimensional, and can be considered to prove the prime factorisation)
\ [D (ijk) = \ sum_ {I '| I} \ sum_ {J' | J} \ {K sum_ '| k} [\ gcd ( i', j ') = 1] [\ gcd (i', k ') = 1] [\ gcd (j', k ') = 1] \]

\[ \sum_{i=1}^a\sum_{j=1}^b\sum_{k=1}^c\sum_{i'|i}\sum_{j'|j}\sum_{k'|k}[\gcd(i',j')=1][\gcd(i', k')=1][\gcd(j', k')=1] \]

\[ \sum_{i'=1}^a\sum_{j'=1}^b\sum_{k'=1}^c[\gcd(i',j')=1][\gcd(i', k')=1][\gcd(j', k')=1]\lfloor\frac{a}{i'}\rfloor\lfloor\frac{b}{j'}\rfloor\lfloor\frac{c}{k'}\rfloor \]

\[ \sum_{i'=1}^a\sum_{j'=1}^b\lfloor\frac{a}{i'}\rfloor\lfloor\frac{b}{j'}\rfloor[\gcd(i',j')=1]\sum_{k'=1}^c[\gcd(i'j', k')=1]\lfloor\frac{c}{k'}\rfloor \]

记:
\[ f(x)=\sum_{k'=1}^c[\gcd(x, k')=1]\lfloor\frac{c}{k'}\rfloor \]

\[ f(x)=\sum_{k'=1}^c\sum_{d|x,d|k'}\mu(d)\lfloor\frac{c}{k'}\rfloor \]

\ [F (x) = \
sum_ {d | x} \ mu (d) \ sum_ {d | k '} \ lfloor \ frac {c} {k'} \ rfloor \] The first \ (g (x ) = \ sum_ {x | k '} \ lfloor \ frac {c} {k'} \ rfloor \) pretreatment out.

Then it may be pretreated \ (f (x) = \ sum_ {d | x} \ mu (d) g (d), x \ in [1, ab] \)

The answer is:
\ [\ sum_ {I '=. 1} ^ A \ sum_ {J' =. 1} ^ B \ lfloor \ FRAC {A} {I '} \ rfloor \ lfloor \ FRAC {B} {J'} \ rfloor [\ gcd (i ' , j') = 1] f (i'j ') \]

#include <algorithm>
#include <cstdio>
using namespace std;
const int m = (1 << 30) - 1;
const int N = 4e6 + 5;
int p[N], mu[N], f[N], c;
bool tag[N];
void sieve(int n) {
    mu[1] = 1;
    for(int i = 2; i <= n; i ++) {
        if(!tag[i]) { p[++ c] = i; mu[i] = -1; }
        for(int j = 1; j <= c && i * p[j] <= n; j ++) {
            tag[i * p[j]] = 1;
            if(i % p[j] == 0) break ;
            mu[i * p[j]] = - mu[i];
        }
    }
}
int main() {
    int a, b, c;
    scanf("%d%d%d", &a, &b, &c);
    if(a > b) swap(a, b);
    if(a > c) swap(a, c);
    if(b > c) swap(b, c);
    int ans = 0; sieve(a * b);
    for(int i = 1; i <= c; i ++) {
        int g = 0;
        for(int j = i; j <= c; j += i) {
            g += c / j;
        }
        for(int j = i; j <= a * b; j += i) {
            (f[j] += mu[i] * g) &= m;
        }
    }
    for(int i = 1; i <= a; i ++) {
        for(int j = 1; j <= b; j ++) {
            if(__gcd(i, j) == 1) {
                (ans += (1ll * (a / i) * (b / j) * f[i * j]) & m) &= m;
            }
        }
    }
    printf("%d\n", ans);
    return 0;
}

Guess you like

Origin www.cnblogs.com/hongzy/p/11704628.html