• hdu5072 容斥+枚举


    这题说的是给了 n 个数字 每个数值大于1 小于100000,n小于100000 ,找出满足下面要求的三人组有多少种 比如abc ( (ab)==(bc)==(ac) ==1 )||( (ab)!=1&&(bc)!=1&&(ac)!=1 )

    (()----表示gcd )计算出这样的三元组的个数。

    这样考虑 三元组必须满足上面的要求 , 那么我们减去不满足的可能情况 abc 计算与 a互质的个数 和与a不互质的个数 得到了b在内的不可行的方案数,然后这样发现会多算一次 如果abc

    (ab)==1 (ac)!=1 在计算c的时候又会计算一次。 然后我们得到了所有的 不肯能方案除以2 得到了不可能的方案数  总方案数减去不可能方案数就得到了(因为数比较小用容斥便可以计算出答案)

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include<string.h>
    #include <vector>
    using namespace std;
    typedef pair<int,int> PF;
    bool vis[100005];
    int prime[10000],num;
    void pri_p(){
       num=0;
       memset(vis,false,sizeof(vis));
       for(long long i=2; i<=100000; ++i)
        if(vis[i]==false){
           prime[num++]=i;
           for(long long j=i*i; j<=100000; j+=i) vis[j]=true;
       }
    }
    int A[100005];
    int P[15];
    int sizea[100005];
    int D[100005];
    vector<PF>F[100005];
    void fenjie(int loc,int len){
        for(int s=1; s<(1<<len); ++s){
           int ss=1,num=0;
           for(int i=0;i<len ;++i){
               if(s&(1<<i)){
                 ss*=P[i]; num++;
               }
           }
           F[loc].push_back(make_pair(ss,num));
       }
       sizea[loc]=F[loc].size();
    }
    void inti(){
        pri_p();
        for(int i=1; i<=100000; ++i){
                int len=0;
                int s=i,num=0;
                while(s>1&&prime[num]!=0){
                     if(s%prime[num]==0){
                        P[len++]=prime[num];
                        while(s>1&&s%prime[num]==0){
                             s/=prime[num];
                        }
                     }
                     num++;
                }
            fenjie(i,len);
        }
    }
    void sum(int loc){
          int sz=sizea[loc];
          for(int i=0; i<sz; ++i){
               PF t=F[loc][i];
               D[t.first]++;
          }
    }
    int jud(int loc){
        int ans=0;
        for(int i=0; i<sizea[loc]; ++i){
            PF f=F[loc][i];
            if(f.second%2==1)ans+=D[f.first];
            else ans-=D[f.first];
        }
        return ans;
    }
    int main()
    {
        inti();
        int cas;
        scanf("%d",&cas);
        for(int cc=1; cc<=cas; ++cc){
            long long n;
            scanf("%I64d",&n);
            memset(D,0,sizeof(D));
            for(int i=0; i<n; ++i){
                scanf("%d",&A[i]);
                sum(A[i]);
            }
            long long ans=0;
            for(int i=0; i<n; ++i){
             long long    S= jud(A[i]);
                 long long noeven = n-S;
                 if(S<=1||noeven==0) continue;
                 ans = ans+noeven*(S-1);
            }
            printf("%I64d
    ",n*(n-1)*(n-2)/6-ans/2);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    POJ 2541 Binary Witch(逆序KMP,好题)
    POJ 2185 Milking Grid (KMP,求最小覆盖子矩阵,好题)
    POJ 3336 Count the string (KMP+DP,好题)
    POJ 1961 2406 (KMP,最小循环节,循环周期)
    POJ 3450 Corporate Identity (KMP,求公共子串,方法很妙)
    KMP模板,最小循环节
    BZOJ 2741 【FOTILE模拟赛】L(可持久化trie)
    BZOJ 2820 YY的GCD(莫比乌斯反演)
    VIJOS 1889 天真的因数分解(莫比乌斯反演,容斥原理)
    BZOJ 2440 完全平方数(莫比乌斯反演,容斥原理)
  • 原文地址:https://www.cnblogs.com/Opaser/p/4048450.html
Copyright © 2020-2023  润新知