hdu5072(容斥,互质判断,同色三角形模型)

传送门

解答传送门

ac代码(位运算实现容斥原理):

#include<bits/stdc++.h>
#define per(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
typedef long long ll;
//#define int long long
const ll inf =2333333333333333LL;
const double eps=1e-8;
int read(){
    char ch=getchar();
    int res=0,f=0;
    while(ch<'0' || ch>'9'){f=(ch=='-'?-1:1);ch=getchar();}
    while(ch>='0'&&ch<='9'){res=res*10+(ch-'0');ch=getchar();}
    return res*f;
}
// ------------------------head
#define mod 1000000007
const int N=100005;
int T,n,a[N],fac[N][10],fcnt[N],prime[N],pcnt,num[N];
bool Notprime[N];
void prime_sieve(){//线性筛
    memset(Notprime,false,sizeof(Notprime));
    pcnt=0;
    for(int i=2;i<=1000;i++){
        if(!Notprime[i])prime[pcnt++]=i;
        for(int j=0;j<pcnt&&i*prime[j]<=1000;j++){
            Notprime[i*prime[j]]=true;
            if(i%prime[j]==0)break;
        }
    }
}
void disi_num(int v,int pos){//disintegrate_num分解质因数
    fcnt[pos]=0;
    int _sqrt=sqrt(v);
    for(int i=2;i<=_sqrt;i++){
        if(v%i==0)fac[pos][fcnt[pos]++]=i;
        while(v%i==0)v/=i;
    }
    if(v>1)fac[pos][fcnt[pos]++]=v;
}
void count_num(){
    for(int i=2;i<=100000;i++){
        for(int j=i+i;j<=100000;j+=i){
            num[i]+=num[j];
        }
    }
}
ll in_ex(int pos){
    ll res=0;
    for(int i=1;i<(1<<fcnt[pos]);i++){
        int cnt=0,mut=1;
        for(int j=0;j<fcnt[pos];j++){
            if(i&(1<<j)){
                cnt++;
                mut*=fac[pos][j];
            }
        }
        if(cnt&1)res+=(ll)num[mut]-1;//减去a[pos]本身,因为他就是这都是它的质因数
        else res-=(ll)num[mut]-1;
    }
    return res;
}

signed main()
{
    prime_sieve();
    scanf("%d",&T);
    while(T--){
        memset(num,0,sizeof(num));
        scanf("%d",&n);
        per(i,1,n){
            scanf("%d",&a[i]);
            num[a[i]]++;
            disi_num(a[i],i);
            //printf("i==%d ",i);//
            //per(j,0,fcnt[i]-1)printf("%d ",fac[i][j]);
            //printf("
");//
        }
        count_num();
        ll res=0;
        for(int i=1;i<=n;i++){
            ll tmp=in_ex(i);
            res+=(ll)(n-1-tmp)*tmp;
        }
        res=(ll)n*(n-1)*(n-2)/6-res/2;
        printf("%lld
",res);
    }

    return 0;
}
原文地址:https://www.cnblogs.com/WindFreedom/p/9697075.html