Codeforces1043F Make It One【gcd为1的最小子集】

题目描述:

给出长度为nn的序列aia_i,选出最少的数(非空)使得它们的gcdgcd11
n,ai3105n,a_i\le3*10^5,无解输出1-1

题目分析:

31053*10^5以内质因子最多的数只有6个,而如果有解,考虑其中质因子最少的数xx,其余每个数一定囊括了一个不在xx中的质因子,且各自囊括的那个质因子不同,(相当于不断去掉gcd的因子)。也就是说答案最多是xx的质因子个数+1,也就是77
这张例子截自洛谷的题解
在这里插入图片描述
那么枚举答案的个数kk,求出选出kk个数组成gcd=1gcd=1的方案f(1)f(1),只需要求出选出kk个数组成gcdgcddd的倍数的方案F(d)F(d),我们就可以通过容斥或莫比乌斯反演求出f(1)f(1)
F(d)=CcntdkF(d)=C_{cnt_d}^kcntdcnt_d表示aia_i中为dd的倍数的数的个数。
由莫比乌斯反演有:f(d)=dxF(x)μ(xd)f(d)=\sum_{d|x}F(x)\mu(\frac xd)
由容斥有:f(d)=F(d)dxf(d)f(d)=F(d)-\sum_{d|x}f(d)

于是就做完了,复杂度O(nlnn7)O(n\ln n*7)

Code:

#include<bits/stdc++.h>
#define maxn 300005
using namespace std;
const int mod = 998244353;
int n,a[maxn],mx,f[maxn],fac[maxn],inv[maxn];
int C(int n,int m){return n<m?0:1ll*fac[n]*inv[m]%mod*inv[n-m]%mod;}
int main()
{
	scanf("%d",&n);
	for(int i=1,x;i<=n;i++) scanf("%d",&x),a[x]++,mx=max(mx,x);
	fac[0]=fac[1]=inv[0]=inv[1]=1;
	for(int i=2;i<=n;i++) fac[i]=1ll*fac[i-1]*i%mod,inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
	for(int i=2;i<=n;i++) inv[i]=1ll*inv[i]*inv[i-1]%mod;
	for(int i=1;i<=mx;i++)
		for(int j=i+i;j<=mx;j+=i) a[i]+=a[j];
	for(int k=1;k<=7;k++){
		for(int i=mx;i>=1;i--){
			f[i]=C(a[i],k);
			for(int j=i+i;j<=mx;j+=i) f[i]=(f[i]-f[j])%mod;
		}
		if(f[1]) return printf("%d\n",k),0;
	}
	puts("-1");
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章