Acdream 1117 Number theory(莫比乌斯反演)

题目链接:

http://acdream.info/problem?pid=1114

 

题意:

给定一个序列,求序列中互质的数的对数。

 

分析:

我们设f(d) 表示gcd恰好为d的数的个数,F(d)表示gcd为d的倍数的个数

因此,F(d) = sigma (f(n))  (n%d==0)

            f(n)= sigma( mu[d]*F[n/d] ) (n%d==0);

因此我们先统计出每个数出现的频数num;

然后用cnt[i]表示i的倍数的个数。

F(i) = C(cnt[i],2);

我们最终要求的结果就是f(1);

代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

#define PB push_back
#define MP make_pair
#define REP(i,n) for(int i=0;i<(n);++i)
#define FOR(i,l,h) for(int i=(l);i<=(h);++i)
#define DWN(i,h,l) for(int i=(h);i>=(l);--i)
#define IFOR(i,h,l,v) for(int i=(h);i<=(l);i+=(v))
#define CLR(vis) memset(vis,0,sizeof(vis))
#define MST(vis,pos) memset(vis,pos,sizeof(vis))
#define MAX3(a,b,c) max(a,max(b,c))
#define MAX4(a,b,c,d) max(max(a,b),max(c,d))
#define MIN3(a,b,c) min(a,min(b,c))
#define MIN4(a,b,c,d) min(min(a,b),min(c,d))
#define PI acos(-1.0)
#define INF 1000000000
#define LINF 1000000000000000000LL
#define eps 1e-8
#define maxn  222223
#define LL long long
using namespace std;

int mu[maxn];
int a[maxn];
bool vis[maxn];
int num[maxn];
int cnt[maxn];
int prime[maxn];
void mobi(){
    int cnt = 0 ;
    CLR(vis);
    mu[1]=1;
    for(int i=2;i<maxn;i++){
        if(!vis[i]){
            prime[cnt++]=i;
            mu[i]=-1;
        }
        for(int j=0;j<cnt&&i*prime[j]<maxn;j++){
            vis[i*prime[j]]=1;
            if(i%prime[j]) mu[i*prime[j]]=-mu[i];//i与prime[j]互质那么mu[i*prime[j]] 等于 mu[i]的基础上再加一个质因子
            else{
                mu[i*prime[j]]==0;//包含有平方因子prime[j]
                break;
            }
        }
    }
}

int main()
{
    mobi();
    int n;
    while(~scanf("%d",&n)){
        int mmax = -1;
        CLR(cnt);
        CLR(num);
        REP(i,n){
            scanf("%d",a+i);
            mmax = max(a[i],mmax);
        }
        REP(i,n) num[a[i]]++;
        FOR(i,1,mmax){
            IFOR(j,i,mmax,i){
                cnt[i]+=num[j];
            }
        }
        LL ans = 0;
        FOR(i,1,mmax)
        ans +=mu[i]*(LL)cnt[i]*(cnt[i]-1)/2;
        printf("%lld\n",ans);
    }
    return 0;
}


 

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