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*(n-1)*(n-2)/6-ans/2);
    }
    return 0;
}

时间: 2024-08-29 23:49:02

hdu5072 容斥+枚举的相关文章

HDU 3929 Big Coefficients(容斥+证明)

(1 + x)^n 的奇数项系数个数等于 2^(bitcount(n)),bitcount(x)为x有多少个1. 然后容斥 枚举每一项存在不存在,然后容斥加加减减即可 这题用二进制枚举会T,只能DFS 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N = 15; typedef long long ll; int t, n; ll

hdu5072 Coprime 2014鞍山现场赛C题 计数+容斥

http://acm.hdu.edu.cn/showproblem.php?pid=5072 Coprime Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Total Submission(s): 354    Accepted Submission(s): 154 Problem Description There are n people standing in a

hdu5072(鞍山regional problem C):容斥,同色三角形模型

现场过的第四多的题..当时没什么想法,回来学了下容斥,又听学长讲了一讲,终于把它过了 题目大意:给定n个数,求全部互质或者全部不互质的三元组的个数 先说一下同色三角形模型 n个点 每两个点连一条边(可以为红色或者黑色),求形成的三条边颜色相同的三角形的个数 反面考虑这个问题,只需要c(n,3)减去不同色的三角形个数即可 对于每一个点,所形成的不同色三角形即为 红色边的数量*黑色边的数量,所以可以O(n)地算出不同色三角形的个数(注意总数要除以2) 然后用c(n,3)减一下即可 对于这个题,如果把

hdu 5664 Lady CA and the graph(树的点分治+容斥)

题意: 给你一个有n个点的树,给定根,叫你找第k大的特殊链 .特殊的链的定义:u,v之间的路径,经过题给的根节点. 题解:(来自BC官方题解) 对于求第k大的问题,我们可以通过在外层套一个二分,将其转化为求不小于mid的有多少个的问题. 接下来我们讨论如何求树上有多少条折链的长度不小于k. 我们考虑常规的点分治(对于重心,求出其到其他点的距离,排序+单调队列),时间复杂度为O(nlog^2n),但是这只能求出普通链的数量. 我们考虑将不属于折链的链容斥掉.也即,我们需要求出有多少条长度不小于mi

hdu 1695 GCD 欧拉函数+容斥

题意:给定a,b,c,d,k x属于[1 , c],y属于[1 , d],求满足gcd(x,y)=k的对数.其中<x,y>和<y,x>算相同. 思路:不妨设c<d,x<=y.问题可以转化为x属于[1,c / k ],y属于[1,d/k ],x和y互质的对数. 那么假如y<=c/k,那么对数就是y从1到c/k欧拉函数的和.如果y>c/k,就只能从[ c/k+1 , d ]枚举,然后利用容斥.详见代码: /****************************

HDU 5155 Harry And Magic Box(组合数学+容斥)

Problem Description One day, Harry got a magical box. The box is made of n*m grids. There are sparking jewel in some grids. But the top and bottom of the box is locked by amazing magic, so Harry can't see the inside from the top or bottom. However, f

hdu1796:容斥入门题

简单的容斥入门题.. 容斥基本的公式早就知道了,但是一直不会写. 下午看到艾神在群里说的“会枚举二进制数就会容斥”,后来发现还真是这样.. 然后直接贴代码了 #include <iostream> #include <stdio.h> #include<string.h> #include<algorithm> #include<string> #include<ctype.h> using namespace std; long l

HDU 6053 TrickGCD 莫比乌斯函数/容斥/筛法

题意:给出n个数$a[i]$,每个数可以变成不大于它的数,现问所有数的gcd大于1的方案数.其中$(n,a[i]<=1e5)$ 思路:鉴于a[i]不大,可以想到枚举gcd的值.考虑一个$gcd(a_1,a_2,a_3…a_n)=d$,显然每个$a_i$的倍数都满足,有$\frac{a_i}{d}$种方案 那么一个d对答案的贡献为\[\prod_{i=1}^{min(a)}{\lfloor\frac{a_i}{d}\rfloor}    \] 但是所有的d计入会有重复情况,考虑容斥,对d进行素数分

【BZOJ4927】第一题 双指针+DP(容斥?)

[BZOJ4927]第一题 Description 给定n根直的木棍,要从中选出6根木棍,满足:能用这6根木棍拼 出一个正方形.注意木棍不能弯折.问方案数. 正方形:四条边都相等.四个角都是直角的四边形. Input 第一行一个整数n. 第二行包含n个整数ai,代表每根木棍的长度. n ≤ 5000, 1 ≤ ai ≤ 10^7 Output 一行一个整数,代表方案数. Sample Input 8 4 5 1 5 1 9 4 5 Sample Output 3 题解:这...这不是沈阳集训的原