HDU 5072 coprime (同色三角形 + 容斥)

Problem Link

5702 Coprime
大意:给你n个整数, ai1e5 ,求三元组 (a,b,c) 任意两两互素或者任意两两都不互素的个数。

Analysis

还记得Ramsey 定理中的那两个蓝色或红色三角形吗。在这 n 个点中如果量两互素则连一条蓝色的边否则连红边,最终问同色三角形个数,总的三角形数为 C3n ,反向考虑,对于每一个点不满足条件的三角形数有多少个?显然找出蓝色边的条数 k k(nk1) 就是答案
最终结果

C3n12(ki)(nki1)

由于 ai1e5 可以用筛法先晒出每个数的倍数 O(nlg(n))
然后对每个数分解质因数,用容斥原理求出它在这些数里面的不互素的个数 O(2k) ,k是他的质因子个数

总结

即使你不知道用筛法去先筛出每个数的倍数,用map来先先存一下也是可以通过的,我第一次就是这样过的,暴力求解因子个数肯定会超时的

AC code

#include 
#include
#include
#include
#include
#include
#include
#define Debug(x) cout<<(x)<
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef pair<int,int > PII;
typedef map<int,int >::iterator MIT;
const int MOD = 1e9+7;
const LL maxn = 1e5+10;
int primesize;
int prime[maxn];

void get_prime()
{
    memset(prime,0,sizeof(prime));
    primesize = 0;
    for(LL i = 2 ; iif(!prime[i])
    {

        prime[primesize++] = i;
        for(LL j = i*i ; j1;
           }
    }
}

int num[maxn];

int divisor[maxn],divisorcnt;

int  get_fact(int a)
{
    divisorcnt = 0;
    for(int i = 0 ; i*prime[i]<=a ; ++i)
        if(a%prime[i] == 0)
    {
        divisor[divisorcnt++] = prime[i];
        while(a%prime[i] == 0)a/=prime[i];
    }
    if(a>1)divisor[divisorcnt++] = a;
    return divisorcnt;
}


void sieve(int max)
{
    for(int i = 2 ; i<=max ; ++i)
    {
        for(int j  = i*2 ; j<=max ; j+=i)
            num[i]+=num[j];
    }
}

int uncoprime(int a,int max)
{
    int divcnt = get_fact(a);
    int ans = 0;
    int sgn = 1;
    for(int i = 1 ; i<(1<int cnt = 0;
        int fact = 1;
        for(int j = 0 ; jif(i&(1<if(cnt & 1)sgn = 1;else sgn = -1;
        if(fact!=1)
        {
            ans += sgn*num[fact];
        }
    }
    return ans;
}

int a[maxn];

int main()
{
    //freopen("H:\\c++\\file\\stdin.txt","r",stdin);

    get_prime();
   int T;scanf("%d",&T);
   while(T--)
   {
       LL n;scanf("%I64d",&n);
       memset(num,0,sizeof(num));
       int ma = 0;
       for(int i =0 ; iscanf("%d",a+i);
           ma = max(a[i],ma);
           num[a[i]]++;
       }
       sieve(ma);
       LL ans = 0;
       for(int i = 0 ; iif(a[i]!=1)
          {
               int k = uncoprime(a[i],ma);
               // Debug(k);
                ans = ans + (k-1)*(n-k);
          }
       }
       ans =  n*(n-1)*(n-2)/6-ans/2;
       printf("%I64d\n",ans);
   }

    return 0;
}

你可能感兴趣的:(同色三角形,容斥原理,算法刷题)