zoukankan      html  css  js  c++  java
  • HDU 5072 Coprime 同色三角形问题

    好吧,我承认就算当时再给我五个小时我也做不出来。

    首先解释同色三角形问题:

    给出n(n >= 3)个点,这些点中的一些被涂上了红色,剩下的被涂上了黑色。然后将这些点两两相连。于是每三个点都会组成一个三角形,

    即总共同拥有sum = C(3,n)个三角形。

    对于一个三角形,假设三个点颜色一样则称其为同色三角形。

    那么一个非常直观的思路就是容斥,sum - 非同色三角形个数ans。

    ans = (sigma (Xi*Yi) ) / 2;(1 <= i <= n,Xi,Yi分别表示与第 i 个点相连的红色点和黑色点的个数。

    )

    状态不好的时候,代码写的就像屎一样。

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdlib>
    #include <cstdio>
    #include <queue>
    #include <cmath>
    #include <stack>
    #include <map>
    
    #pragma comment(linker, "/STACK:1024000000")
    #define EPS (1e-8)
    #define LL long long
    #define ULL unsigned long long
    #define INF 0x3f3f3f3f
    
    using namespace std;
    
    int divi[100010][130];
    
    bool is[100010];
    
    int num[100010];
    
    int mem[100010];
    
    int ch[1001];
    
    int Check(int x)
    {
        int ans = 0;
        while(x)
            ans += (x&1),x >>= 1;
        return ans&1 ? 1:-1;
    }
    
    int main()
    {
        int n = 100000,i,j,k;
    
        for(i = 0;i <= 1000; ++i)
            ch[i] = Check(i);
    
        for(i = 1;i <= n; ++i)
            divi[i][0] = 0;
    
        memset(is,false,sizeof(is));
    
        for(i = 2;i <= n; ++i)
        {
            if(is[i] == false)
            {
                divi[i][++divi[i][0]] = i;
    
                for(j = i+i;j <= n; j += i)
                {
                    divi[j][++divi[j][0]] = i;
                    is[j] = true;
                }
            }
        }
    
    
        int Max,Mul,t;
        int wf;
        for(i = 1;i <= n; ++i)
        {
            Max = (1<<divi[i][0]) - 1;
            wf = divi[i][0];
            for(j = 1;j <= Max; ++j)
            {
                for(Mul = 1,t = 1,k = wf;k >= 1; --k,t <<= 1)
                {
                    if((j&t) && j != t)
                        Mul *= divi[i][k];
                }
                if(Mul != 1)
                    divi[i][++divi[i][0]] = Mul*ch[j];
            }
        }
    
        int T,tmp;
        LL ans,sum;
    
        int Top;
    
        scanf("%d",&T);
    
        while(T--)
        {
            scanf("%d",&n);
    
            memset(is,false,sizeof(is));
    
            for(i = 1,Top = 0;i <= n; ++i)
            {
                scanf("%d",&num[i]);
                is[num[i]] = true;
                Top = max(Top,num[i]);
            }
    
            ans = 0;
    
            memset(mem,-1,sizeof(mem));
            LL anw = 0;
            for(i = 1;i <= n; ++i)
            {
                tmp = num[i];
                ans = 0;
                for(j = divi[tmp][0];j >= 1; --j)
                {
                    if(mem[abs(divi[tmp][j])] != -1)
                        sum = mem[abs(divi[tmp][j])]*(divi[tmp][j]/abs(divi[tmp][j]));
                    else
                    {
                        sum = 0;
                        for(k = abs(divi[tmp][j]);k <= Top; k += abs(divi[tmp][j]))
                            sum += is[k] ? 1 : 0;
                        mem[abs(divi[tmp][j])] = sum;
                        sum *= (divi[tmp][j]/abs(divi[tmp][j]));
                    }
                    ans += sum;
                }
                if(ans)
                    anw += (n-ans)*(ans-1);
            }  
            LL tn = n;
            printf("%I64d
    ",tn*(tn-1)*(tn-2)/6 -anw/2);
        }
    
        return 0;
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    


  • 相关阅读:
    由二进制移位想到的
    KDJ指标详解
    PMP考试结束
    转K线理论初级二
    日本地震效应
    Baseline之流水先生的见解
    KDJ判断原则
    转K线理论初级一
    管理学法则
    今天提到KW,特此@Mark一下
  • 原文地址:https://www.cnblogs.com/zhchoutai/p/7220240.html
Copyright © 2011-2022 走看看