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

题目

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

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


分析

显然不能直接求出来,考虑容斥,
即用最大公约数为1的倍数的情况减去最大公约数不为1的情况
后面这一坨显然可以一直容斥,那么首先统计出每个数字出现的次数,
枚举倍数可以算出每个数字及它们的倍数出现的次数,
那么最大公约数为(x)(x)的倍数的情况也就是(C_x^4)
时间复杂度(O(nlog 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);
	}
}
原文地址:https://www.cnblogs.com/Spare-No-Effort/p/13822477.html