思路:
首先看数据范围1e4就知道不能用n^2的方法。
所以我们要统计每个数作为gcd对答案的贡献。
而统计一个区间内有多少个
gcd(i,j)=k
的无序数对,当然就是上莫比乌斯喽~
反演式:
对于这道题,由于是给定的n个数,而不是一个区间,所以我们不能o(1)的求出F(i)的值了,所以先nlogn的预处理出F(i)的的值,然后nlogn的统计出所有f(i)。
然后对于每个f(i),我们把它的贡献加到答案中:
f(i)∗i∗(i−1)
(注意取mod)
#include<stdio.h>
#include <iostream>
#include<string.h>
#include<math.h>
#include<algorithm>
#define eps 1e-8
typedef long long int lli;
using namespace std;
const int maxn = 1e4+10;
const int mod = 10007;
bool isprime[maxn];
//int phi[maxn];
int prime[maxn],miu[maxn];
void moblus(){
int cnt = 0;miu[1] = 1;
for(lli i = 2;i < maxn;i++){
if(!isprime[i]){
prime[cnt++] = i,miu[i] = -1;//phi[i] = i-1;
}
for(lli j = 0;j < cnt && i*prime[j] < maxn;j++){
lli x = prime[j];
isprime[i*x] = 1;
if(i%x){
miu[i*x] = -miu[i];
//phi[i*x] = phi[i] * phi[x];
}
else{
miu[i*x] = 0;
//phi[i*x] = phi[i] * x;
break;
}
}
}
}
int a[maxn];
int f[maxn];
int gc[maxn];
int main(){
moblus();
int n,v;
while(~scanf("%d",&n)){
memset(a,0,sizeof(a));
memset(f,0,sizeof(f));
memset(gc,0,sizeof(gc));
int maxa = -0x3f3f3f3f;
for(int i = 1;i <= n;i++){
scanf("%d",&v);
a[v]++;
maxa = max(maxa,v);
}
for(int i = 1;i <= maxa;i++){
for(int j = 1;j*i<=maxa;j++){
f[i] += a[i*j];
}
}
for(int i = 2;i <= maxa;i++){
for(int j = 1;j*i<=maxa;j++){
gc[i] += miu[j]*f[j*i]*f[j*i];
}
}
int ans = 0;
for(int i = 2;i <= maxa;i++){
ans += gc[i]%mod *i%mod*(i-1)%mod;
ans %= mod;
}
printf("%d\n",ans%mod);
}
return 0;
}