挑出数组a里 三个数满足三个数两两互质或者三个数两两不互质 。
反过来求就是可以用总的方案数 C(n,3) - (a,b互质, b,c不互质) 三个数中有 a和b互质,b和c 不互质 , a,c的关系无所谓,不管a,c是否互质,结果就可以是 与b不互质的与b互质的 我们都会吧情况多算了两次,所以 算出的总结果要除以2。。。问题就是求一个数组中与a[i]互质的有多少个, 防着写了一个代码
#include<bits/stdc++.h>
using namespace std;
int n;
const int maxn = 100010;
int a[maxn];
long long s[maxn];
bool isprime[maxn];
int prime[maxn];
int tot =0;
int fac[100];
//打出素数表
void getprime(int M)
{
for(int i = 2; i<=M; i++)
{
if(isprime[i])continue;
prime[tot++] = i;
for(int j = i+i; j<=M; j+=i)
{
isprime[j] = true;
}
}
}
long long rongchi()
{
long long ans = 0;
for(int i = 1; i<=n; i++)
{
int m =a[i];
int num =0;
long long sum = 0;
for(int j =0; j<tot&&prime[j]*prime[j]<=m; j++)
{
if(m%prime[j]==0)
{
fac[num++] = prime[j];
while(m%prime[j]==0)
m/=prime[j];
}
}
if(m!=1)fac[num++] = m;
// fac存下来每个数的因子
for(int j =1; j<(1<<num); j++)
{
int op=0;
int temp =1;
for(int k = 0; k<num; k++)
{
if((1<<k)&j)
{
temp *= fac[k];
op++;
}
}
if(op&1)
{
sum+=s[temp];
}
else
{
sum-=s[temp];
}
}
if(sum==0) sum =1;
ans+=(sum-1)*(n-sum);
}
return ans/2;
}
int flag[100000];
int main()
{
int T;
scanf("%d",&T);
memset(isprime,false,sizeof(isprime));
getprime(100000);
while(T--)
{
scanf("%d",&n);
memset(flag,0,sizeof(flag));
memset(s,0,sizeof(s));
int gm = 0;
for(int i = 1; i<=n; i++)
{
scanf("%d",&a[i]);
flag[a[i]] =1;
gm= max(gm,a[i]);
}
//记录下来 s[i] 表示 在a中有多少个是可以整除 i的。
for(int i = 2; i<=gm; i++)
{
for(int j =i; j<=gm; j+=i)
{
if(flag[j])
s[i]++;
}
}
printf("%lld\n",1LL*n*(n-1)*(n-2)/6 - rongchi());
}
return 0;
}