POJ 3904

4 篇文章 0 订阅

//题意,给出n个数,问有多少组(a,b,c,d)公约数为1,注意并不一定两两互质!因为不一定两两都互质,那么从相反的方向着手比较方便!即先统计出(a,b,c,d)公约数>1的对数,然后用总数减去即可!
容斥原理应用,以2为因子的数有a个,3为因子 的数有b个,6为因子的数有c个,n个数不互质的四元组个数为C(4,a)+C(4,b)-C(4,c) (含奇数个素因子的加,偶数个素因子的减),下面就是统计出2,3,5这些因子的倍数的个数,对C(4,a)容斥!

就是因为不一定满足两两互斥的条件,因此要考虑逆着求,然后每个素因子以及他们的积是加还是减是固定的,因此用它容斥就可以了!

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
int n;
int a[10010];
bool is[10010];
vector<int> pr;
void div(int x){
    pr.clear();
    for(int i=2; i*i<=x; i++){
        if(x % i == 0) pr.push_back(i);
        while(x % i == 0) x /= i;
    }
    if( x > 1 ) pr.push_back(x);
}
int Count[10010];
int num[10010];
void solve(int x){
    div(x);
    int size = pr.size();
    int all = (1<<size);
    for(int i=1; i<all; i++){
        long long t = 1;
        long long ci = 0;
        for(int j=0; j < size; j++){
            if(i&(1<<j)){
                t *= pr[j];
                ci++;   
            }   
        }
        Count[t]++;
        num[t] = ci;
    }
}
long long c(long long a){
    return a*(a-1)*(a-2)*(a-3)/24;  
}
int main(){
    while(cin>>n){
        memset(Count, 0, sizeof(Count));
        for(int i=1; i<=n; i++) scanf("%d", &a[i]), solve(a[i]);
        long long res = 0;
        for(int i=1; i<=10000; i++){
            if(Count[i]){
                if(num[i]&1) res += c(Count[i]);    
                else res -= c(Count[i]);
            }
        }   
        res = c(n) - res;
        printf("%lld\n", res);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值