简略题意:给出
n
个数,任选
枚举
gcd
,那么我们要计算的就是当前
gcd
对答案的贡献。
令
f(i)
为所有方案中
gcd=i
对答案的贡献,
F(i)
表示
i|gcd
对答案的贡献。
假若有
x
个数为
F(i)=1∗C(x,1)+2∗C(x,2)+3∗C(x,3)+...+x∗C(x,x)
=x∗(C(x−1,1)+C(x−1,2)+C(x−1,3)+...+C(x−1,x−1))=x∗2x−1
。
而
f(i)=∑maxvi=1∑i|dμ(d/i)∗F(d)
。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL maxn = 1100000;
const LL mod = 1e9+7;
LL mul(LL a, LL b) {
a *= b;
a = a % mod;
a += mod;
a %= mod;
return a;
}
LL add(LL a, LL b) {
a += b;
if(a >= mod) a-=mod;
return a;
}
bool tag[maxn];
LL p[maxn/10];
LL mob[maxn]; //莫比乌斯线性筛
LL cnt;
void GetPrime(){
cnt = 0;
mob[1] = 1;
for(LL i = 2; i < maxn; i++){
if(!tag[i]) {
p[cnt++] = i;
mob[i] = -1;
}
for(LL j = 0; j < cnt && p[j] * i < maxn; j++){
tag[i * p[j]] = 1;
if(i % p[j] == 0) {
mob[i*p[j]] = 0;
break;
}
mob[i*p[j]] = -mob[i];
}
}
}
LL F[maxn], f[maxn];
struct ASSWECAN {
LL n;
LL cnt[maxn];
LL pow2[maxn];
LL ans[maxn];
void solve() {
scanf("%d", &n);
for(LL i = 1; i <= n; i++) {
LL v;
scanf("%d", &v);
cnt[v]++;
}
GetPrime();
pow2[0] = 1;
for(LL i = 1; i <= 1000000; i++) pow2[i] = mul(pow2[i-1], 2);
for(LL i = 2; i <= 1000000; i++) {
LL s = 0;
for(LL j = i; j <= 1000000; j+=i) s += cnt[j];
if(s) {
F[i] = mul(s, pow2[s-1]);
}
}
for(LL i = 1; i <= 1000000; i++) {
for(LL j = i; j <= 1000000; j+=i)
f[i] = add(mul(mob[j/i], F[j]), f[i]);
}
LL res = 0;
for(LL i = 2; i <= 1000000; i++)
res = add(res, mul(f[i], i));
printf("%lld\n", res);
}
} solver;
int main(){
solver.solve();
return 0;
}