ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

HDU-5072 补集转化+容斥原理

2019-09-09 10:51:32  阅读:206  来源: 互联网

标签:HDU int 补集 容斥 因子 异色 三角形 互质 数量


题意:给n个数,求满足一下条件的三元组(a,b,c)数量:a,b,c两两互质或者a,b,c两两不互质。

解法:这道题非常巧妙地运用补集转化和容斥原理。首先我们令这n个数为n个点,然后两两之间连边如果是互质连黑色不互质连红色,那么这个图就会变成完全图。那么题目就是要求我们计算这个完全图的同色三角形数量。观察发现同色三角形数量非常难求但是异色三角形数量好求,因为每个异色三角形对应三个点必定有两个点是连接两条异色边的。并且这种关系是一一对应的,那么我们就可以对于每个点求出连接该点的异色边对数,就可以求出与该点相关的异色三角形数量(注意这里用的词是相关,那么一个异色三角形与两个异色点相关所以答案要除以2)。

那么问题就变成怎么快速找到一个点连接的异色边对数呢?很容易想到如果点i的异色边数为e[i]的话,同色边数就是n-e[i]-1,那么对数就是(e[i])*(n-e[i]-1)。但是问题是怎么快速计算e[i]的数量?也就是说对于a[i]怎么快速求出n个数中有几个数与a[i]互质?

这个问题是此题关键。我们用到容斥原理:与一个数a[i]不互质的数数量=至少拥有a[i]的一个质因子数量-至少拥有a[i]的两个质因子数量+至少拥有a[i]的三个质因子数量-至少拥有a[i]的四个质因子数量......。那么我们就先求出mul[i]代表n个数中拥有i因子的数的数量(这里具体是用到状态压缩枚举的办法,具体看代码很好懂),得到mul之后对于a[i]与它不互质的数的个数就是a[i]的质因子组合用利用mul数组计算上诉的容斥原理式子得到。

到这里此题可解了。

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,m,a[N],mul[N],e[N];
vector<int> fac[N];

void prework() {  //预处理1-100000的因子 
    for (int i=1;i<=100000;i++) {
        int n=i;
        for (int j=2;j*j<=n;j++) {
            if (n%j==0) {
                fac[i].push_back(j);
                while (n%j==0) n/=j;
            }
        }
        if (n>1) fac[i].push_back(n);
    }
}

int main()
{
    prework();
    int T; cin>>T;
    while (T--) {
        scanf("%d",&n);
        for (int i=1;i<=n;i++) scanf("%d",&a[i]);
        memset(mul,0,sizeof(mul));
        memset(e,0,sizeof(e));
        for (int i=1;i<=n;i++) {
            int ALL=1<<fac[a[i]].size();
            for (int j=0;j<ALL;j++) {
                int sum=1;
                for (int k=0;k<fac[a[i]].size();k++)
                    if (j&(1<<k)) sum=sum*fac[a[i]][k];
                mul[sum]++;  //代表是sum倍数的a[i]的个数++    
            }
        }
        for (int i=1;i<=n;i++) {
            int ALL=1<<fac[a[i]].size();
            for (int j=1;j<ALL;j++) {
                int sum=1,sig=-1;
                for (int k=0;k<fac[a[i]].size();k++)
                    if (j&(1<<k)) sum=sum*fac[a[i]][k],sig*=-1;
                e[i]+=sig*mul[sum];  //容斥原理求与a[i]不互质的数个数(包括自己) 
            }
            e[i]=n-e[i];  //补集就是与a[i]互质的数个数(不包括自己) 
            if (a[i]==1) e[i]=n-1;
        }
        
        long long ans=1,tmp=0;
        for (int i=n;i>n-3;i--) ans=ans*i;
        ans=ans/6;  //计算全集C(n,3) 
        
        for (int i=1;i<=n;i++) tmp+=(long long)(e[i])*(n-e[i]-1);  //计算异色三角形数量 
        printf("%lld\n",ans-tmp/2);
    }
    return 0;
}

 

标签:HDU,int,补集,容斥,因子,异色,三角形,互质,数量
来源: https://www.cnblogs.com/clno1/p/11490374.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有