1. 程式人生 > >HihoCoder - 1867: GCD (莫比烏斯容斥)

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

rip air mut sat ins isf contains push hoc

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; }

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