莫比乌斯反演

Give you a sequence a1, a2, a3...,an, the question is how many pair(ai, aj) that ai and aj is coprime? (i < j)

acdreamoj 1114 

f(d) 表示gcd为d的倍数的数的对数

g(d)表示gcd恰好为d的数的对数

f(d) = ∑ g(n) (n % d == 0)

g(d) = ∑  mu[n / d] * f(n) (n %d == 0)

所以 g(1) = ∑mu[n] * f(n)

求一下mu【】,枚举一下n

typedef long long LL ;

const   int  maxn = 222228 ;

int   prime[maxn] , primenum ;
bool  is[maxn] ;
int   mu[maxn] ;

void   mobius(int n){
       memset(is , 0 , sizeof(is)) ;
       primenum = 0 ;
       is[1] = mu[1] = 1 ;
       for(int i = 2 ; i <= n ; i++){
            if(! is[i]){
                 prime[primenum++] = i ;
                 mu[i] = -1 ;
            }
            for(int j = 0 ; j < primenum ; j++){
                if(i * prime[j] > n)  break ;
                is[i * prime[j]] = 1 ;
                if(i % prime[j] == 0){
                    mu[i * prime[j]] = 0 ;
                    break ;
                }
                mu[i*prime[j]] = -mu[i] ;
            }
       }
}

int  a[maxn] , cnt[maxn] , num[maxn] ;
int  main(){
     mobius(222222)  ;
     int n , mx , i  , j  ;
     while(scanf("%d" , &n) != EOF){
          mx = 0  ;
          for(i = 1 ; i <= n ; i++){
              scanf("%d" , &a[i]) ;
              mx = max(mx , a[i]) ;
          }
          memset(cnt , 0 , sizeof(cnt)) ;
          memset(num , 0 , sizeof(num)) ;
          for(i = 1 ; i <= n ; i++) num[a[i]]++ ;
          for(int i = 1 ; i <= mx ; i++){
              for(int j = i ; j <= mx ; j += i)
                 cnt[i] += num[j] ;
          }
          LL s = 0 ;
          for(i = 1 ; i <= mx ; i++)
              s += ((LL)cnt[i] * (LL)(cnt[i]-1) / 2) * (LL)mu[i] ;
          printf("%lld\n" , s) ;
     }
     return 0 ;
}








你可能感兴趣的:(莫比乌斯反演)