题意:给你n个数,现在让你求出有多少个四元组,满足这四个数的最大公约数等于1,n<=10000,每个数<=10000,多组询问,对于每个询问回答有多少个四元组满足条件.
分析:设\(f(d)\)为选出\(4\)个数\(gcd\)为\(d\)的个数,设\(F(d)\)表示为选出\(4\)个数公约数为\(d\)的方案数,所以由莫比乌斯反演,则有\(f(d)=\sum_{d|x}F(x)μ(\frac xd)\)
故\(ans=f(1)=\sum_{x=1}^{10000}F(x)μ(x)\)
即对于一个数\(i(1<=i<=10000)\),设有\(sum[i]\)个数是它的倍数,然后求\(C_{sum[i]}^4*μ(i)\)累加进\(ans\)即可.
恶心的\(long\) \(long......\)
#include<bits/stdc++.h>
#define LL long long
using namespace std;
inline int read(){
int s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
return s*w;
}
const int N=10005;
int n,mu[N],v[N],prime[N],sum[N];
inline void get_mu(){
int m=0;mu[1]=1;
for(int i=2;i<=10000;i++){
if(!v[i]){
v[i]=i;
prime[++m]=i;
mu[i]=-1;
}
for(int j=1;j<=m;j++){
if(prime[j]*i>10000)break;
v[prime[j]*i]=prime[j];
if(i%prime[j]==0)break;
else mu[i*prime[j]]=-mu[i];
}
}
}
inline LL C(int n){return 1ll*n*(n-1)*(n-2)*(n-3)/24;}
int main(){
get_mu();
while(~(scanf("%d",&n))){
LL ans=0;for(int i=1;i<=10000;i++)sum[i]=0;
for(int i=1;i<=n;i++){
int j,m=read();
for(j=1;j*j<m;j++)
if(m%j==0)sum[j]++,sum[m/j]++;
if(j*j==m)sum[j]++;
}
for(int i=1;i<=10000;i++)
ans=ans+1ll*mu[i]*C(sum[i]);
printf("%lld\n",ans);
}
return 0;
}