#容斥,倍数,排列组合#洛谷 2714 四元组统计

题目

给定一个长度为\(n\)的序列\(a\)

\[\sum_{i=1}^n\sum_{j=i+1}^n\sum_{k=j+1}^n\sum_{l=k+1}^n[gcd(a_i,a_j,a_k,a_l)==1] \]


分析

显然不能直接求出来,考虑容斥,
即用最大公约数为1的倍数的情况减去最大公约数不为1的情况
后面这一坨显然可以一直容斥,那么首先统计出每个数字出现的次数,
枚举倍数可以算出每个数字及它们的倍数出现的次数,
那么最大公约数为\(x\)\(x\)的倍数的情况也就是\(C_x^4\)
时间复杂度\(O(n\log n)\)


代码

#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
typedef long long lll;
const int N=10001;
lll c[N]; int n;
inline signed iut(){
	rr int ans=0; rr char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans;
}
inline void print(lll ans){
	if (ans>9) print(ans/10);
	putchar(ans%10+48);
}
signed main(){
	while (scanf("%d",&n)==1){
		for (rr int i=1;i<N;++i) c[i]=0;
		for (rr int i=1;i<=n;++i) ++c[iut()];
		for (rr int i=1;i<N;++i)
		for (rr int j=i<<1;j<N;j+=i) c[i]+=c[j];
		for (rr int i=N-1;i;--i){
			c[i]=c[i]*(c[i]-1)*(c[i]-2)*(c[i]-3)/24;
			for (rr int j=i<<1;j<N;j+=i) c[i]-=c[j];
		}
		print(c[1]),putchar(10);
	}
}
posted @ 2020-10-15 19:38  lemondinosaur  阅读(107)  评论(0编辑  收藏  举报