∑
i
=
1
n
∑
j
=
i
+
1
n
∑
k
=
j
+
1
n
=
f
(
a
i
,
a
j
,
a
k
)
a
i
,
a
j
\sum\limits_{i=1}^{n}\sum\limits_{j=i+1}^{n}\sum\limits_{k=j+1}^{n}=f(a_i,a_j,a_k)\quad a_i,a_j
i=1∑nj=i+1∑nk=j+1∑n=f(ai,aj,ak)ai,aj 是较小的两数
易得简单做法排序后通过枚举前两个数结合
G
C
D
GCD
GCD 计算,但是复杂的为
n
2
l
o
g
n
n^2logn
n2logn 会
T
E
L
TEL
TEL。
思路
因数分解:预处理出可能会用到的所有数的所有因数。因数分解比较耗时,所以在每个
c
a
s
e
case
case 里再去处理是不现实的。
试想在排序后我们枚举
a
i
a
j
a_i\;a_j
aiaj 计算两者
G
C
D
GCD
GCD 的贡献,计算的就是因数对答案的贡献不过是最大公约数 。我们可以用一个
f
o
r
for
for 遍历数组,每到一个数就记录该数所有出现过的因数对答案的贡献最大公约数对答案才有贡献,但我们不计算最大公约数,我们记录每一个约数的贡献,其中一定包括最大公约数,而出现过就保证了是公约数
s
u
m
[
x
]
+
=
c
n
t
[
x
]
∗
(
n
−
i
)
n
−
i
sum[x]{+}{=}cnt[x]*(n-i)\;n-i
sum[x]+=cnt[x]∗(n−i)n−i 是距离,应题目。记录之后需
+
+
c
n
t
[
x
]
{++}cnt[x]
++cnt[x] 记录出现过的次数
容斥:考虑
x
x
x 就是最大公约数,那所有
x
x
x 的倍数作为最大公约数时的贡献都应该减去。因为
x
x
x 与
x
x
x 的倍数是同在一个因数分解的桶中的,而我们
f
o
r
for
for 遍历时
+
+
c
n
t
[
x
]
{++}cnt[x]
++cnt[x] 每一个因数。 Think Twice, Code Once
#include<bits/stdc++.h>#defineilinline#definegetgetchar#defineputputchar#defineisisdigit#definereregister#defineintlonglong#definedfor(i,a,b)for(re int i=a;i<=b;++i)#definedforr(i,a,b)for(re int i=a;i>=b;--i)#definedforn(i,a,b)for(re int i=a;i<=b;++i,put(10))#definemem(a,b)memset(a,b,sizeof a)#definememc(a,b)memcpy(a,b,sizeof a)#definepr114514191981#definegg(a) cout<<a,put(32)#defineINF0x7fffffff#definett(x) cout<<x<<'\n'#definelsi<<1#definersi<<1|1#definela(r) tr[r].ch[0]#definera(r) tr[r].ch[1]#definelowbit(x)(x&-x)usingnamespace std;typedefunsignedint ull;intread(void){
re int x=0,f=1;re char c=get();while(!is(c))(f=c==45?-1:1),c=get();while(is(c)) x=(x<<1)+(x<<3)+(c^48),c=get();return x*f;}voidwrite(int x){if(x<0) x=-x,put(45);if(x>9)write(x/10);put((x%10)^48);}#definewriteln(a)write(a),put(10)#definewritesp(a)write(a),put(32)#definewritessp(a)put(32),write(a)constint N=1e5+10,M=3e4+10,SN=1e4+10,mod=19930726;int n,ans,a[N],cnt[N],sum[N];
vector<int> ve[N];signedmain(){int T=read();dfor(i,1,N)for(re int j=i;j<N;j+=i) ve[j].push_back(i);while(T--){mem(cnt,0),mem(sum,0),ans=0;
n=read();dfor(i,1,n) a[i]=read();sort(a+1,a+n+1);dfor(i,1,n){int len=ve[a[i]].size()-1;dfor(j,0,len){
sum[ve[a[i]][j]]+=cnt[ve[a[i]][j]]*(n-i);++cnt[ve[a[i]][j]];}}dforr(i,a[n],1){for(re int j=i<<1;j<N;j+=i) sum[i]-=sum[j];
ans+=sum[i]*i;}writeln(ans);}return0;}