题目大意:
给定一个序列,求有多少个子序列的gcd等于1。
首先想到枚举每个数作为gcd,统计次数,再容斥一下。
统计答案时当这个数有偶数个约数时系数是-1,奇数个约数时是1。
然后我们发现这就是个莫比乌斯函数。
用线性筛求出莫比乌斯函数就可以了。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define M 1000000007
#define N 100010
int x,i,j,k,n,m,f[N],S,Ma,Ans,mu[N],p[N],Cnt;
bool b[N];
inline int Max(int x,int y){return x<y?y:x;}
inline int Pow(int x,int y){
if(y==0)return 1;
int Ans=Pow(x,y>>1);
Ans=1ll*Ans*Ans%M;
if(y&1)return 1ll*Ans*x%M;
return Ans;
}
inline void Init(){
mu[1]=1;
for(i=2;i<=Ma;i++){
if(!b[i])p[++Cnt]=i,mu[i]=-1;
for(j=1;j<=Cnt&&p[j]*i<=Ma;j++){
b[p[j]*i]=1;
if(!(i%p[j]))break;
mu[p[j]*i]=-mu[i];
}
}
}
int main(){
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%d",&x);Ma=Max(Ma,x);
S=sqrt(x);
for(j=1;j<=S;j++)
if(x%j==0){
f[j]++;
if(j*j<x)f[x/j]++;
}
}
Init();
for(i=1;i<=Ma;i++)Ans=(Ans+(Pow(2,f[i])-1)*mu[i])%M;
printf("%d\n",(Ans+M)%M);
return 0;
}