题目链接:
ACdream 1114
题意:
给你一个序列
a
,求出这个序列中互质数的有多少对。
其中所有的整数的都小于等于
题解:
f(d)
为
gcd
恰好为
d
的数的对数。
所以,
F(d)=∑f(n)。其中(n%d==0)
。
莫比乌斯反演一下就可以得到,
f(d)=∑μ(nd)∗F(n)
,其中
(n%d==0)
。
我们最后所要求的答案就是
f(1)
, 也就是
∑μ(n)∗F(n)
。
设
Count[d]
是
a
这个序列中为
介绍一下莫比乌斯反演:
公式:
如果 f(n),g(n) 是数论函数,且满足:
f(n)=∑d∣ng(d)
则有莫比乌斯反演:
g(n)=∑d∣nμ(nd)f(d)=∑d∣nμ(d)f(nd)
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 222222+10;
int isprime[N],mu[N],prime[N];
int cnt;
void Mobius(int n)
{
int i,j;
cnt=0;mu[1]=1;
for(i=2;i<=n;i++){
if(!isprime[i]){
prime[cnt++]=i;
mu[i]=-1;
}
for(j=0;j<cnt&& i*prime[j]<=n;j++){
isprime[i*prime[j]]=1;
if(i%prime[j])
mu[i*prime[j]]=-mu[i];
else {mu[i*prime[j]]=0;break;}
}
}
}
int a[N];
int n;
ll ans;
ll num[N];
ll Count[N];
int main()
{
Mobius(222222);
while(~scanf("%d",&n))
{
ans = 0;
int Maxx = - 0x7fffffff;
memset(Count, 0, sizeof(Count));
memset(num, 0, sizeof(num));
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
Maxx = max(Maxx, a[i]);
}
for(int i=1;i<=n;i++){
++num[a[i]];
}
for(int i=1;i<=Maxx;i++)
{
for(int j=i;j<=Maxx;j+=i)
{
Count[i] += num[j];
}
}
for(int i=1;i<=Maxx;i++){
ans += (mu[i] * 1LL * Count[i] * (Count[i] - 1)) >> 1;
}
printf("%lld\n",ans);
}
return 0;
}