题意:
给出序列,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) = sumlimits_{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
", ans);
}
}