Live2d Test Env

HihoCoder - 1867: GCD (莫比乌斯容斥)

Sample Input

6
1 6 2 5 3 4

Sample Output

10

You are given a {1, 2, ..., n}-permutation a[1], a[2], ..., a[n]. How many pairs of integers (i, j) satisfy 1 ≤ i ≤ j ≤ n and gcd(i, j) = gcd(a[i], a[j]) = 1? Here gcd means greatest common divisor.

Input

First line contains an integer n. (1 ≤ n ≤ 200000)

Second line contains n space-separated integers a[1], a[2], ..., a[n] which form a permutation.

Output

One line contains the answer.

题意:给定N的排列a[],问有多少对(i,j),满足gdc(i,j)=gcd(a[i],a[j])=1;

思路:我们知道区间互质对统计可以用莫比乌斯来容斥,对于每个数d,其贡献=mu[d]*C(含d的个数,2);

但是这里有两个条件,可以说是个二维的。 那么,我们枚举第一位的d,然后在第二维里正常的操作。

复杂度:因为每个数在第一维最多被使用log次,第二维也是,所以复杂度不大于N*logN*logN。加上我们有一些减枝,比如mu[i]=0时不操作。

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=200010;
int a[maxn],mu[maxn],pos[maxn],num[maxn],N; vector<int>G[maxn]; ll ans;
void init()
{

    rep(i,1,N) {
        if(i==1) mu[1]=1; G[i].push_back(i);
        for(int j=i+i;j<=N;j+=i) mu[j]-=mu[i],G[j].push_back(i);
    }
}
ll get(int x)
{
    ll res=0;
    for(int i=x;i<=N;i+=x)
      rep(j,0,G[a[i]].size()-1) num[G[a[i]][j]]++;
    for(int i=x;i<=N;i+=x)
      rep(j,0,G[a[i]].size()-1) res+=1LL*(num[G[a[i]][j]]-1)*mu[G[a[i]][j]];
    for(int i=x;i<=N;i+=x)
      rep(j,0,G[a[i]].size()-1) num[G[a[i]][j]]=0;
    return res/2;
}
int main()
{
    scanf("%d",&N); init();
    rep(i,1,N) scanf("%d",&a[i]),pos[a[i]]=i;
    rep(i,1,N)
      if(mu[i]) ans+=1LL*mu[i]*get(i);
    printf("%lld\n",ans+(a[1]==1));
    return 0;
}

 

posted @ 2019-01-04 19:22  nimphy  阅读(396)  评论(0编辑  收藏  举报