题目
http://codeforces.com/contest/585/problem/E
n
个
分析
题目太神QAQ。
考虑选出一个非空集合
S,GCD(S)=k
的情况有多少种
假设有
cnt
个数是
k
的倍数
设
则有
ans[k]=2cnt−1
那么答案应该是
A[k]=ans[k]−∑k|jans[j]
我们已经知道了 GCD=k 的情况有多少种,再考虑选出一个数与k互质的情况
但是很难求,还是考虑容斥
选出一个数和 k 求
考虑 k 是一个质数的情况
不妨计算选出一个数使得
那么答案为不选k的倍数 Ans=2cnt(i)∗(n−cnt(i))
考虑 k 是两个质数的乘积,答案为一个质数的答案+另一个质数的答案-两个质数乘积的答案。莫比乌斯函数?
设
其中 mu[i] 为莫比乌斯函数
而
A
数组的容斥过程类似,可以一起容斥
代码很简练
#include <bits/stdc++.h>
#define maxn 10000010
using namespace std;
int n, a[maxn], h[maxn];
int mu[maxn], p[maxn], primes;
bool vis[maxn];
const int N = maxn - 10;
const long long mod = 1e9 + 7;
long long pow2[maxn];
int main(){
scanf("%d", &n);
for(int i = 1; i <= n; i ++)
scanf("%d", &a[i]), h[a[i]] ++;
long long t;
mu[1] = 1;
for(int i = 2; i <= N; i ++){
if(!vis[i]){p[primes ++] = i; mu[i] = -1;}
for(int j = 0; j < primes; j ++){
if((long long)p[j] * i > N)break;
vis[p[j] * i] = true;
if(i % p[j] == 0){mu[p[j] * i] = 0; break;}
mu[p[j] * i] = -mu[i];
}
}
pow2[0] = 1;
for(int i = 1; i <= N; i ++)pow2[i] = (pow2[i-1] << 1) % mod;
long long Ans = 0;
for(int i = 2; i <= N; i ++){
if(mu[i] == 0)continue;
int c = 0;
for(int j = i; j <= N; j += i)
c += h[j];
if(c == 0)continue;
t = (pow2[c] - 1) * (n - c) % mod;
if(mu[i] == -1)Ans = (Ans + t) % mod;
else Ans = (Ans - t + mod) % mod;
}
printf("%I64d\n", Ans % mod);
return 0;
}