POJ 3904 容斥原理

题意:给n个数,求它们能够组成的四元组(a, b, c, d)的个数,其中gcd(a, b, c, d) = 1。

思路:容斥原理求出不满足要求的四元组个数,

           比如若这n个数只有2,3,5三种质因数,设P[i]为n个数中有约数为i的数的个数,则不满足的个数为:

           C(P[2], 4) + C(P[3], 4) + C(P[5], 4) - C(P[2 * 3], 4) - C(P[2 * 5], 4) - C(P[3 * 5], 4) + C(P[2 * 3 * 5], 4);

           需要注意的是只有几个不同质数的乘积才能计入答案,如上式中不应考虑4,9,12等。

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#define For(i,j,k) for(LL i = j;i <= k;i ++)

const int N = 10010;

using namespace std;
typedef long long LL;
LL C[N], Num[N], cnt[N];

void init(){
	For(i,2,N - 1){
		C[i] = i * (i - 1) * (i - 2) * (i - 3) / 24;
		if(!Num[i])Num[i] = 1;
		for(LL j = i * 2;j < N;j += i)
			Num[j] = max(Num[j], Num[i] + 1);
	}
}

void solve(LL x){
	LL p[15], s = 0;
	for(LL i = 2;i * i <= x;i ++)
		if(x % i == 0){
			p[s++] = i;
			while(x % i == 0)x /= i;
		}
	if(x > 1)p[s++] = x;
	for(LL i = 1;i < (1 << s);i ++){
		LL sum = 1;
		For(j,0,s-1)
			if(i & (1 << j))sum *= p[j];
		cnt[sum]++;
	}
}

int main(){
	init();
	LL n, x;
	while(scanf("%lld", &n) == 1){
		memset(cnt, 0, sizeof(cnt));
		For(i,1,n) scanf("%lld", &x), solve(x);
		LL Ans = C[n];
		For(i,2,N-1){
			if(Num[i] & 1)
				Ans -= C[cnt[i]];
			else Ans += C[cnt[i]];
		}
		printf("%lld\n", Ans);
	}
	return 0;
}


          

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值