题目描述
传送门
题目大意:有n张邮票,可以从中任意选取一张,然后可以从剩下的邮票中选取任意张构成一个集合,使集合中所有邮票的价值与选取出的价值互质,且选中的集合中的元素必须不互质。
题解
这道题的容斥系数与莫比乌斯函数mu有关。
我们先从质数开始考虑,我们选出所有某个质数的倍数构成备选的集合,那么从剩下的元素中任意选一个,再从备选集合中选出任意个,构成的都是合法方案。但是我们考虑6,在计算2,3的时候其实都计算到了他。所以要用容斥来去重。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 10000000
#define M 500003
#define LL long long
#define p 1000000007
using namespace std;
int pd[N+3],prime[N+3],mu[N+3],mark[N+3];
int mi[M],n,a[M];
LL ans;
void init()
{
mu[1]=1;
for (int i=2;i<=N;i++) {
if (!pd[i]) {
prime[++prime[0]]=i;
mu[i]=-1;
}
for (int j=1;j<=prime[0];j++) {
if (i*prime[j]>N) break;
pd[i*prime[j]]=1;
if (i%prime[j]==0) {
mu[i*prime[j]]=0;
break;
}
mu[i*prime[j]]=-mu[i];
}
}
mi[0]=1;
for (int i=1;i<=n;i++) mi[i]=mi[i-1]*2%p;
for (int i=2;i<=N;i++) {
int c=0;
if (mu[i]==0) continue;
for (int j=i;j<=N;j+=i)
c+=mark[j];
mu[i]=-mu[i];
ans=(ans+(LL)mu[i]*(n-c)%p*(mi[c]-1)%p)%p;
}
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%d",&a[i]),mark[a[i]]++;
init();
printf("%I64d\n",(ans%p+p)%p);
}