Number theory
Time Limit: 2000/1000MS (Java/Others)
Memory Limit: 128000/64000KB (Java/Others)
Problem Description
This time I will give you some straight!
Give you a sequence a1, a2, a3...,an, the question is how many pair(ai, aj) that ai and aj is coprime? (i < j)
Input
The input consists of multiple test cases. Each test case contains two lines.
The first line contains a single interger n.
The second line contains n interger.
All the intergers are between 1 and 222222.
Output
For each test case, you should output one line that contains the answer for the test case.
Sample Input
2 1 2
Sample Output
1
Source
yehuijie
Manager
题意:
给你一个序列a,求出这个序列中互质数的有多少对
解题思路:
莫比乌斯反演,网上有个思路讲的比较清晰:
f(d) 为 gcd 恰好为 d 的数的对数, F(d) 为 gcd 为 d 的倍数的对数, μ(d) 表示莫比乌斯函数
F(d) = ∑ f(n) 其中( n % d == 0 )
莫比乌斯反演一下就可以得到, f(d) = ∑ μ(n / d) * F(n) 其中( n % d == 0)
所以我们最后所要的答案就是 f(1), 也就是 ∑ μ(n) * F(n)
下面代码中,cnt[d]是a这个序列中为d的倍数的数字的个数,num[d]是a这个序列中d的个数,所以F[n] = C(cnt[n], 2).
AC代码:
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; const int MAXN = 222222+10; typedef long long LL; LL cnt[MAXN]; int mu[MAXN],prime[MAXN]; int num[MAXN]; bool vis[MAXN]; int pcnt; /*求解Mobinus函数*/ void Mobinus() { memset(vis,0,sizeof(vis)); pcnt=0; mu[1]=1; for(int i=2;i<MAXN;i++){ if(!vis[i]){ prime[pcnt++]=i; mu[i]=-1; } for(int j=0;j<pcnt&&i*prime[j]<MAXN;j++){ vis[i*prime[j]]=1; if(i%prime[j])mu[i*prime[j]]=-mu[i];//i是素数的情况 else { mu[i*prime[j]]=0; break; } } } } int main() { Mobinus(); int n; while(scanf("%d",&n)!=EOF){ LL Max=-99999999,ans=0; LL a[MAXN]; memset(cnt,0,sizeof(cnt)); memset(num,0,sizeof(num)); for(int i=0;i<n;i++){ scanf("%lld",&a[i]); Max=max(a[i],Max); } for(int i=0;i<n;i++){ num[a[i]]++; } for(int i=1;i<=Max;i++){ for(int j=i;j<=Max;j+=i) cnt[i]+=num[j]; } for(int i=1;i<=Max;i++){ ans+=(mu[i]*cnt[i]*(cnt[i]-1))>>1; } printf("%lld\n",ans); } return 0; }