AcWing 231. 天码 (容斥)打卡

题目:https://www.acwing.com/problem/content/233/

题意:给你n个不同的数,让你选取一个四元组,gcd为1,让你求这样的四元组数量是多少

思路:我们单独直接去算肯定不行,正难反易,我们可以用总的减去其他gcd不是1的,也就是四个数同时有一个相同且不是1的因子,然后我们按gcd值分组

但是中间有很多分组其实有重复的值,比如  2,3  那么 6就是他们重复的,这个题不能n^2过,我们只能拆每个数的因子,然后用这些因子构造出其他与当前

数构造出不是1因子的个数

#include<bits/stdc++.h>
#define ll long long
#define mod 1000000007
#define maxn 100005
using namespace std;
ll n,a[maxn],cnt;
int vis[maxn];
int flag[maxn];
ll prime[maxn];
ll C(ll n,ll m){
     return n*(n-1)*(n-2)*(n-3)/24;
}
void make(ll x){
    cnt=0;
    for(int i=2;i*i<=x;i++){
        if(x%i==0){
            prime[cnt++]=i;
            while(x%i==0) x/=i;        
        }
    }
    if(x>1) prime[cnt++]=x;
    for(int i=1;i<(1<<cnt);i++){
        ll cur=1;
        ll num=0;
        for(int j=0;(i>>j)>0;j++){
            if((i>>j)&1){
                num++;
                cur*=prime[j];
            }
        }
        vis[cur]++;
        flag[cur]=num;
    }
}
int main()
{
    while(scanf("%lld",&n)!=EOF){
        memset(vis,0,sizeof(vis));
        memset(flag,0,sizeof(flag));
        for(int i=0;i<n;i++){
            scanf("%lld",&a[i]); 
            make(a[i]);
        }
        ll sum=C(n,4);
        for(int i=2;i<=10000;i++){
            if(flag[i]&1){
                sum-=C(vis[i],4);
            }
            else{
                sum+=C(vis[i],4);
            } 
        }
        printf("%lld
",sum);
    }
}
原文地址:https://www.cnblogs.com/Lis-/p/11296638.html