[题目链接]
https://codeforces.com/contest/585/problem/E
[题解]
令 (s_{n}) 表示最大公约数恰好为 (n) 的集合个数 , (f_{n}) 表示与 (n) 互质的数个数。
那么答案为 (sum{s_{i}f_{i}})。
考虑计算 (f) , 令 (c_{i}) 表示 (i) 的出现次数。
那么有 (f_{n} = sum_{i}{[gcd(i , n) = 1]c_{i}} = sum_{i}{c_{i}}sum_{d|i,d|n}{mu(d)} = sum_{d|n}{mu(d)}sum_{d|i}{c_{i}})。
不妨令 (g_{k} = sum_{k|i}{c_{i}} , g'_{k} = mu(k)g(k)) , 那么 (f_{n} = sum_{d|n}{g'_{d}})。
再考虑求 (s_{i}) , 不妨令 (s'_{i}) 为最大公约数为 (i) 倍数的方案数 , 显然 (s'_{i} = 2 ^ {g_{i}} - 1)。
又有 (s'_{i} = sum_{i|d}{s_{d}})。
这两个式子都是 (a_{k} = sum_{d|k}{b_{k}}) 或 (a_{k} = sum_{k|d}{b_{k}}) 的形式 , 可以求狄利克雷前缀和 (第二个式子实质上是求逆)。
时间复杂度 : (O(NlogN))
[代码]
#include<bits/stdc++.h>
using namespace std;
#define rep(i , l , r) for (int i = (l); i < (r); ++i)
typedef long long LL;
const int MN = 5e5 + 5 , MM = 1e7 + 5 , mod = 1e9 + 7;
int n , lim , s[MM] , two[MN] , a[MN] , tot[MM] , g[MM] , pr[MM / 10] , cnt , mu[MM] , vis[MM];
inline void inc(int &x , int y) {
x = x + y < mod ? x + y : x + y - mod;
}
inline void dec(int &x , int y) {
x = x - y >= 0 ? x - y : x - y + mod;
}
inline void prework(int n) {
mu[1] = 1;
for (int i = 2; i <= n; ++i) {
if (!vis[i]) pr[++cnt] = i , mu[i] = -1;
for (int j = 1; j <= cnt && i * pr[j] <= n; ++j) {
vis[i * pr[j]] = 1;
if (i % pr[j] == 0) {
mu[i * pr[j]] = 0;
break;
} else mu[i * pr[j]] = -mu[i];
}
}
}
int main() {
scanf("%d" , &n); two[0] = 1;
for (int i = 1; i <= 500000; ++i) two[i] = 2ll * two[i - 1] % mod;
for (int i = 1; i <= n; ++i) {
scanf("%d" , &a[i]);
++tot[a[i]];
}
lim = *max_element(a + 1 , a + 1 + n); prework(lim);
for (int i = 1; i <= cnt; ++i)
for (int j = lim / pr[i]; j; --j)
tot[j] += tot[j * pr[i]];
for (int i = 1; i <= lim; ++i) g[i] = (1ll * tot[i] * mu[i] % mod + mod) % mod;
for (int i = 1; i <= cnt; ++i)
for (int j = 1; j * pr[i] <= lim; ++j)
inc(g[j * pr[i]] , g[j]);
for (int i = 1; i <= lim; ++i) s[i] = two[tot[i]] - 1;
for (int i = cnt; i; --i)
for (int j = 1; j * pr[i] <= lim; ++j)
dec(s[j] , s[j * pr[i]]);
int ans = 0;
for (int i = lim; i > 1; --i) inc(ans , 1ll * s[i] * g[i] % mod);
printf("%d
" , ans);
return 0;
}