zoukankan      html  css  js  c++  java
  • 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 1000
    long 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
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    LeetCode-Search a 2D Matrix
    Cocos2d-x 学习(1)—— 通过Cocos Studio创建第一个Demo
    SpringMVC经典系列-12基于SpringMVC的文件上传---【LinusZhu】
    poj 2126 Factoring a Polynomial 数学多项式分解
    [每天读书半小时] 2015-6-8 设计模式
    LeetCode_Path Sum II
    MySql截取DateTime字段的日期值
    Fiddler2 中文手册
    fiddler2抓包工具使用图文教程
    Fiddler2 抓取手机APP数据包
  • 原文地址:https://www.cnblogs.com/oneshot/p/4046511.html
Copyright © 2011-2022 走看看