hdu 5072 Coprime

挑出数组a里 三个数满足三个数两两互质或者三个数两两不互质 。 

 反过来求就是可以用总的方案数 C(n,3) - (a,b互质, b,c不互质)          三个数中有 a和b互质,b和c 不互质 , a,c的关系无所谓,不管a,c是否互质,结果就可以是 与b不互质的与b互质的          我们都会吧情况多算了两次,所以 算出的总结果要除以2。。。问题就是求一个数组中与a[i]互质的有多少个, 防着写了一个代码

#include<bits/stdc++.h>
using namespace std;
int n;
const int maxn = 100010;
int a[maxn];
long long s[maxn];
bool isprime[maxn];
int prime[maxn];
int tot =0;
int fac[100];
//打出素数表
void getprime(int M)
{
    for(int  i = 2; i<=M; i++)
    {
        if(isprime[i])continue;
        prime[tot++] = i;
        for(int j = i+i; j<=M; j+=i)
        {
            isprime[j]  = true;
        }
    }
}
long long rongchi()
{
    long long ans = 0;
    for(int i = 1; i<=n; i++)
    {
        int m =a[i];
        int  num =0;
        long long sum = 0;
        for(int j =0; j<tot&&prime[j]*prime[j]<=m; j++)
        {
            if(m%prime[j]==0)
            {
                fac[num++] = prime[j];
                while(m%prime[j]==0)
                    m/=prime[j];
            }
        }

        if(m!=1)fac[num++] = m;
        // fac存下来每个数的因子
        for(int j =1; j<(1<<num); j++)
        {
            int op=0;
            int temp =1;
            for(int k = 0; k<num; k++)
            {
                if((1<<k)&j)
                {
                    temp *= fac[k];
                    op++;
                }
            }
            if(op&1)
            {
                sum+=s[temp];
            }
            else
            {
                sum-=s[temp];
            }
        }
        if(sum==0) sum =1;
        ans+=(sum-1)*(n-sum);
    }
    return ans/2;
}
int flag[100000];
int main()
{
    int T;
    scanf("%d",&T);
    memset(isprime,false,sizeof(isprime));
    getprime(100000);
    while(T--)
    {
        scanf("%d",&n);
        memset(flag,0,sizeof(flag));
        memset(s,0,sizeof(s));
        int gm = 0;
        for(int  i = 1; i<=n; i++)
        {
            scanf("%d",&a[i]);
            flag[a[i]] =1;
            gm= max(gm,a[i]);

        }
        //记录下来 s[i] 表示  在a中有多少个是可以整除 i的。
        for(int i = 2; i<=gm; i++)
        {
            for(int j =i; j<=gm; j+=i)
            {
                if(flag[j])
                    s[i]++;
            }
        }
        printf("%lld\n",1LL*n*(n-1)*(n-2)/6 - rongchi());
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/theflowerofac/article/details/52789398