HDU5212 CODE【莫比乌斯函数】

题意:

给出序列,1≤i,j≤n,求gcd(a[i],a[j])∗(gcd(a[i],a[j])−1)之和。

题解 :

\(F(x)\)表示:有多少数对的gcd为x的倍数。
\(f(x)\)表示:有多少数对的gcd恰好为x。

\(F(x)\)很好求滴!
然后就可以施展容斥了。

举个例子: \(f(1) = F(1) - F(2) - F(3) + F(6)\)
٩̋(๑˃́ꇴ˂̀๑)۶: \(f(x) = \sum\limits_{x|y} F(y)μ(\frac{y}{k})\)

code

#include <iostream>
using namespace std;
#define MOD (10007)
const int MAXN = 1000000;
bool check[MAXN+10];
int prime[MAXN+10];
int mu[MAXN+10];
void Moblus() {
    memset(check, false, sizeof(check));
    mu[1] = 1; int tot = 0;
    for(int i = 2; i <= MAXN; i++) {
        if( !check[i] ) {
            prime[tot++] = i;
            mu[i] = -1;
        }
        for(int j = 0; j < tot; j++) {
            if(i * prime[j] > MAXN) break;
            check[i * prime[j]] = true;
            if( i % prime[j] == 0) {
                mu[i * prime[j]] = 0;
                break;
            } else {
                mu[i * prime[j]] = -mu[i];
            }
        }
    }
}
int T, n;
int a[10002], c[10002], f[10002];
int main() {
    Moblus();  
    while (~ scanf("%d", &n)) {
        int mx = -1;
        for (int i = 1; i <= 10000; i ++) c[i] = 0, f[i] = 0;
        for (int i = 1; i <= n; i ++) {
            scanf("%d", &a[i]); if (mx < a[i]) mx = a[i];
            for (int t = 1; t * t <= a[i]; t ++) {
                if (a[i] % t == 0) {
                    c[t] ++; if (t * t != a[i]) c[a[i] / t] ++;
                }
            }
        }
        for (int i = 1; i <= mx; i ++) {
            for (int j = i; j <= mx; j += i) {
                (f[i] += (c[j]*c[j]*mu[j/i])) %= MOD;
            }
        }
        int ans = 0;
        for (int g = 1; g <= mx; g ++) {
            ans = ans + g*(g-1)%MOD*f[g]; ans = (ans % MOD + MOD) % MOD;
        }
        printf("%d\n", ans);
    }
}
posted @ 2017-10-12 07:49  RUSH_D_CAT  阅读(170)  评论(0编辑  收藏  举报