题意:
在n个数中选出三个数使得 两两互质或不互质
直接求两两互质和不互质的个数比较麻烦
所以求出不满足条件的组合
先记录下b[i]:表示与第i个数互质的数的个数
c[i]表示与第i个数不互质的个数
b[i]*c[i]则表示选择了第i个数有这么多种情况不符合条件
sum+=b[i]*c[i](i=1...n)
每种情况出现了两次所以 sum/2
所以
ans=C(n,3)-sum/2;
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
#include <queue>
#include <stack>
#include <vector>
#include <deque>
#include <set>
#include <map>
#define IN freopen ("in.txt" , "r" , stdin);
#define OUT freopen ("out.txt" , "w" , stdout);
typedef long long LL;
const int MAXN = 1001;//点数的最大值
const int MAXM = 20006;//边数的最大值
const int INF = 11521204;
const int mod=6;
int a[802],b[888],c[888];
int gcd(int a,int b)
{
if(b==0)
return a;
return gcd(b,a%b);
}
int C(int n,int k)
{
int sum=1;
for(int i=1; i<=k; i++)
sum=sum*(n-i+1)/i;
return sum;
}
int main()
{
int t,n;
//IN;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i=0; i<n; i++)
{
scanf("%d",&a[i]);
b[i]=c[i]=0;
}
int sum=0;
for(int i=0; i<n; i++)
{
for(int j=0; j<n; j++)
{
if(i==j) continue;
if(gcd(a[j],a[i])==1)
b[i]++;
else c[i]++;
}
}
for(int i=0; i<n; i++)
sum+=b[i]*c[i];
printf("%d\n",C(n,3)-sum/2);
}
return 0;
}