zoukankan      html  css  js  c++  java
  • ACdream 1114(莫比乌斯反演)

    传送门:Number theory

    题意:给n个数,n 和 每个数的范围都是 1---222222,求n个数中互质的对数。

    分析:处理出每个数倍数的个数cnt[i],然后进行莫比乌斯反演,只不过这里的F(i)=cnt[i]*(cnt[i]-1)/2.

    #pragma comment(linker,"/STACK:1024000000,1024000000")
    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <cmath>
    #include <limits.h>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <cstdlib>
    #include <stack>
    #include <vector>
    #include <set>
    #include <map>
    #define LL long long
    #define mod 100000000
    #define inf 0x3f3f3f3f
    #define eps 1e-6
    #define N 222222
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define PII pair<int,int>
    using namespace std;
    inline int read()
    {
        char ch=getchar();int x=0,f=1;
        while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
        while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    bool vis[N+5];
    int mu[N+5],prime[N+5],sum[N+5];
    void Mobius()
    {
        memset(vis,false,sizeof(vis));
        mu[1]=1;
        int tot=0;
        for(int i=2;i<=N;i++)
        {
            if(!vis[i])
            {
                prime[tot++]=i;
                mu[i]=-1;
            }
            for(int j=0;j<tot;j++)
            {
                if(i*prime[j]>N)break;
                vis[i*prime[j]]=true;
                if(i%prime[j]==0)
                {
                    mu[i*prime[j]]=0;
                    break;
                }
                else
                {
                    mu[i*prime[j]]=-mu[i];
                }
            }
        }
        for(int i=1;i<=N;i++)sum[i]=sum[i-1]+mu[i];
    }
    int num[N+5],cnt[N+5];
    LL solve(int n)
    {
        LL res=0;
        for(int i=1;i<=n;i++)
        {
            if(!cnt[i])continue;
            res+=1LL*mu[i]*cnt[i]*(cnt[i]-1)/2;
        }
        return res;
    }
    
    int main()
    {
        int n,x;
        Mobius();
        while(scanf("%d",&n)>0)
        {
            memset(num,0,sizeof(num));
            memset(cnt,0,sizeof(cnt));
            int mx=0;
            for(int i=1;i<=n;i++)
            {
                x=read();
                num[x]++;
                mx=max(x,mx);
            }
            for(int i=1;i<=mx;i++)
                for(int j=i;j<=mx;j+=i)
                cnt[i]+=num[j];
            LL ans=solve(mx);
            printf("%lld
    ",ans);
        }
    }
    View Code
  • 相关阅读:
    第八章 多线程编程
    Linked List Cycle II
    Swap Nodes in Pairs
    Container With Most Water
    Best Time to Buy and Sell Stock III
    Best Time to Buy and Sell Stock II
    Linked List Cycle
    4Sum
    3Sum
    Integer to Roman
  • 原文地址:https://www.cnblogs.com/lienus/p/4296737.html
Copyright © 2011-2022 走看看