题意:给n个数,为有多少互质对;
解法:然后求出mou值,然后求出1,2,3...max的倍数的个数,每个出现在gcd中的对数(num[i]*(num[i]-1))/2,乘上mou值进行容斥计算。
代码:
/******************************************************
* author:xiefubao
*******************************************************/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <stack>
#include <string.h>
//freopen ("in.txt" , "r" , stdin);
using namespace std;
#define eps 1e-8
#define zero(_) (abs(_)<=eps)
const double pi=acos(-1.0);
typedef long long LL;
const int Max=222225;
const int INF=1000000007;
LL num[Max];
LL rem[Max];
int mou[Max];
int n;
void init()
{
for(LL i=2; i<Max; i++)
if(!mou[i])
{
mou[i]=i;
for(LL j=i*i; j<Max; j+=i)
mou[j]=i;
}
mou[1]=1;
for(int i=2;i<Max;i++)
{
if(i/mou[i]%mou[i]==0) mou[i]=0;
else
{
mou[i]=-mou[i/mou[i]];
}
}
}
int main()
{
init();
while(scanf("%d",&n)==1)
{
memset(rem,0,sizeof rem);
memset(num,0,sizeof num);
int ma=0;
for(int i=0; i<n; i++)
{
int a;
scanf("%d",&a);
ma=max(ma,a);
rem[a]++;
}
ma++;
for(int i=1; i<ma; i++)
{
for(int j=i; j<ma; j+=i)
{
num[i]+=rem[j];
}
}
LL ans=0;
for(int i=1; i<ma; i++)
{
ans+=mou[i]*(num[i]*(num[i]-1))/2;
}
cout<<ans<<'\n';
}
return 0;
}