Coprime HDU - 5072


Coprime  HDU - 5072 


There are n people standing in a line. Each of them has a unique id number.
Now the Ragnarok is coming. We should choose 3 people to defend the evil. As a group, the 3 people should be able to communicate. They are able to communicate if and only if their id numbers are pairwise coprime or pairwise not coprime. In other words, if their id numbers are a, b, c, then they can communicate if and only if [(a, b) = (b, c) = (a, c) = 1] or [(a, b) ≠ 1 and (a, c) ≠ 1 and (b, c) ≠ 1], where (x, y) denotes the greatest common divisor of x and y.
We want to know how many 3-people-groups can be chosen from the n people.


Input

The first line contains an integer T (T ≤ 5), denoting the number of the test cases.
For each test case, the first line contains an integer n(3 ≤ n ≤ 10 5), denoting the number of people. The next line contains n distinct integers a 1, a 2, . . . , a n(1 ≤ a i ≤ 10 5) separated by a single space, where a i stands for the id number of the i-th person.


Output

For each test case, output the answer in a line.

Sample Input

1
5
1 3 9 10 2

Sample Output

4


ti題意: 給你 n 個數,讓你求  取出三個數,三個這三個數兩兩互質或者兩兩不互質  的方案數。


思路: 顯然直接求方案數沒有頭緒,我們考慮先求出總的方案數 "C(n,3) ", 然後減去不符合條件的,

那麼對於不符合條件的: 可以簡化三元爲二元,即 不符合條件的必定是一組 gcd(a,b)=1  一組gcd(b,c) !=1;

那麼我們可以直接枚舉  b,  對於每一個 b  找出與他不互質的數的個數 k-1,(除去他自己)  與他互質的數的個數有

(n-k); 

那麼方案數 ans=(n-k)*(k-1)/2 ;

那麼對於  K  ,我們可以用容斥求解;

那麼最後的答案就是  tot=C(n,3)- ans';

具體看 :點擊打開鏈接

注意預處理, 可能會  T ;

代碼有些不好理解,看了好久~~~


#pragma comment(linker, "/STACK:1024000000,1024000000")
//#include <bits/stdc++.h>
#include<string>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<queue>
#include<stack>
#include<vector>
#include<algorithm>
#define maxn 100010
#define INF 0x3f3f3f3f
#define eps 1e-8
#define MOD 1000000007
#define ll long long
using namespace std;

int A[maxn];
int n;
int len1;
bool vis[maxn],Vis[maxn];
int pri[maxn];
int fac[maxn];
int F[maxn][maxn/1000];
int siz[maxn];
int ret[maxn];
void init()
{
    len1=0;
    memset(vis,0,sizeof vis);
    for(int i=2;i<maxn;i++)
    {
        if(!vis[i])
            pri[len1++]=i;
        for(int j=0;j<len1&&i*pri[j]<maxn;i++)
        {
            vis[i*pri[j]]=0;
            if(i%pri[j]==0)  break;
        }
    }
}
void Init()
{
    int len;
    for(int i=1;i<maxn;i++)
    {
        int x=i;
        len=0;
        for(int k=0;pri[k]*pri[k]<=x;k++)
        {
            if(x%pri[k] ==0 )
            {
                F[i][len++]=pri[k];
                x/=pri[k];
                while(x%pri[k]==0)
                    x/=pri[k];
            }
        }
        if(x>1)        F[i][len++]=x;
        siz[i]=len;
    }
}
ll func()
{
    memset(ret,0,sizeof ret);
    for(int i=1;i<maxn;i++)
        for(int j=i;j<maxn;j+=i)
        {
            if(Vis[j])
                ret[i]++;
        }
	ll ans=0;
	for(int i=0;i<n;i++)
    {
        int cnt=siz[A[i]];
        int st=1<<cnt;
        ll tmp=0;
        for(int k=1;k<st;k++)
        {
            int val = 1;
            int w = 0;
            for(int j = 0;j < cnt;j++)
            {
                if(k & (1<<j))
                {
                    val *= F[A[i]][j];
                    w ^= 1;
                }
            }
            if(w)  tmp += ret[val]-1;
            else tmp -= ret[val]-1;
        }
        ans+=tmp*=(n-tmp-1);
    }
    return ans;
}
int main()
{
    int T;
    scanf("%d",&T);
    init();
    Init();
    while(T--)
    {
        memset(Vis,0,sizeof Vis);
        scanf("%d",&n);
        for(int i = 0;i < n;i++)
            scanf("%d",&A[i]),Vis[A[i]]=1;
        ll ans = func();
        ll tot =(ll) n*(n-2)*(n-1)/6;
        printf("%lld\n",tot-ans/2);
    }
    return 0;
}







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章