首页 > 代码库 > hdu5072(鞍山regional problem C):容斥,同色三角形模型

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

现场过的第四多的题。。当时没什么想法,回来学了下容斥,又听学长讲了一讲,终于把它过了

题目大意:
给定n个数,求全部互质或者全部不互质的三元组的个数

先说一下同色三角形模型

n个点 每两个点连一条边(可以为红色或者黑色),求形成的三条边颜色相同的三角形的个数

反面考虑这个问题,只需要c(n,3)减去不同色的三角形个数即可

对于每一个点,所形成的不同色三角形即为 红色边的数量*黑色边的数量,所以可以O(n)地算出不同色三角形的个数(注意总数要除以2)

然后用c(n,3)减一下即可

对于这个题,如果把互质看作红色边,不互质看作黑色边,就可以转化为同色三角形问题了

那如何求 互质的个数和不互质的个数呢

我们可以预处理范围内每个数的倍数的数量,然后对每个数分解质因子,最后容斥一下即可

代码:

#include <iostream>#include <stdio.h>#include<string.h>#include<algorithm>#include<string>#include<ctype.h>using namespace std;#define MAXN 1000long long n;int a[100010];int prime[100010];int num[100010];int isnotprime[100010];int num_prime=0;int fac[100010][10];int np[100010];long long gcd(long long a,long long b){    return b?gcd(b,a%b):a;}long long lcm(long long a,long long b){    return a/gcd(a,b)*b;}void setprime(){    for(int i = 2 ; i < MAXN ; i ++)    {        if(!isnotprime[i])             prime[num_prime ++]=i;        for(int j=0;j<num_prime&&i*prime[j]<MAXN;j++)        {            isnotprime[i * prime[j]] = 1;            if(!(i%prime[j] ) )                break;        }    }    return ;}void setfac(int x,int pos){    np[pos]=0;    for(int i=0;i<num_prime;i++)    {        if(!(x%prime[i]))        {            fac[pos][np[pos]++]=prime[i];        }        while(!(x%prime[i]))        {            x/=prime[i];        }    }    if(x>1)    {        fac[pos][np[pos]++]=x;    }}long long iae(int pos){    long long res=0;    for(int i=1;i<(1<<np[pos]);i++)    {        long long mut=1,tmp=0;        for(int j=0;j<np[pos];j++)        {            if(i&(1<<j))            {                mut*=fac[pos][j];                tmp++;            }        }        if(tmp&1)        {            res+=num[mut]-1;        }        else        {            res-=num[mut]-1;        }    }    return res;}void setnum(){    for(int i=2;i<=100000;i++)    {        for(int j=i+i;j<=100000;j+=i)            num[i]+=num[j];    }}int main(){    #ifndef ONLINE_JUDGE        //freopen("in.txt","r",stdin);    #endif    int T;    setprime();    scanf("%d",&T);    while(T--)    {        memset(num,0,sizeof(num));        scanf("%I64d",&n);        for(int i=0;i<n;i++)        {            scanf("%d",a+i);            num[a[i]]++;            setfac(a[i],i);        }        setnum();        long long ans=0;        for(int i=0;i<n;i++)        {            int tmp=iae(i);            ans+=(n-1-tmp)*tmp;        }        ans=n*(n-1)*(n-2)/6-ans/2;        printf("%I64d\n",ans);    }    return 0;}

 

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