Loading

四元组统计

链接:https://www.luogu.com.cn/problem/P2714

原链接:https://www.acwing.com/problem/content/233/

题目描述:题目应该说的很清楚了。

题解:假如你按莫比乌斯那一套走的话令\(p_{i}\)表示\(i\)在数列中出现的次数你会发现会算重。而且由于莫比乌斯函数太玄学,貌似都无法容斥。

所以我们要换一种思路,考虑反演那一套:

\(f_{x}\)表示\(\gcd=x\)的四元组个数,\(g_{x}\)表示\(x|\gcd\)的四元组个数。

\(g_{x}=\sum_{x|i}f_{i}\),反演得\(f_{x}=\sum_{x|i}g_{i}μ({\frac{i}{x}})\)

由于\(g_{x}\)可以快速求,所以我们可以求出\(f_{x}\)

#include<iostream>
#define N 30000
using namespace std;
long long res,t,n,F[30001],f[30001],miu[30001],a[30001];
bool prime[30001];
int main()
{
	for (int i=1;i<=N;++i)
		miu[i]=1;
	for (int i=2;i<=N;++i)
		if (!prime[i])
		{
			for (int j=i;j<=N;j+=i)
			{
				prime[j]=1;
				miu[j]=-miu[j];
				if ((j/i)%i==0)
					miu[j]=0;
			}
		}
	while (cin>>n)
	{
		res=0;
		for (int i=1;i<=N;++i)
			f[i]=F[i]=0;
		for (int i=1;i<=n;++i)
		{
			cin>>a[i];
			F[a[i]]++;
		}
		for (int i=1;i<=N;++i)
		{
			for (int j=i;j<=N;j+=i)
				f[i]+=F[j];
			f[i]=f[i]*(f[i]-1)*(f[i]-2)*(f[i]-3)/24;
		}
		for (int i=1;i<=N;++i)
			res+=f[i]*miu[i];
		cout<<res<<endl;
	}
	return 0;
}
posted @ 2022-12-14 21:40  zhouhuanyi  阅读(60)  评论(0)    收藏  举报