poj3904 Sky Code

容斥搞出 gcd 不是 \(1\) 的四元组个数。
参考

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
typedef long long ll;
int n, cnt[10005], num[10005], uu, fac[35], din;
ll ans;
void div(int x){
	for(int i=2; i*i<=x; i++)
		if(x%i==0){
			fac[din++] = i;
			while(x%i==0)	x /= i;
	}
	if(x>1)	fac[din++] = x;
}
void cal(){
	din = 0;
	scanf("%d", &uu);
	div(uu);
	for(int i=1; i<(1<<din); i++){
		int tmp=1, qwq=0;
		for(int j=0; j<din; j++)
			if(i&(1<<j)){
				tmp *= fac[j];
				qwq++;
			}
		cnt[tmp]++;
		num[tmp] = qwq;
	}
}
ll C(int x){
	return (ll)(x-3)*(x-2)*(x-1)*x/24;
}
int main(){
	while(scanf("%d", &n)!=EOF){
		ans = 0;
		memset(cnt, 0, sizeof(cnt));
		memset(num, 0, sizeof(num));
		for(int i=1; i<=n; i++)
			cal();
		for(int i=2; i<=10000; i++){
			if(num[i]&1)	ans += C(cnt[i]);
			else	ans -= C(cnt[i]);
		}
		printf("%lld\n", C(n)-ans);
	}
	return 0;
}
posted @ 2018-03-13 18:54  poorpool  阅读(92)  评论(0编辑  收藏  举报