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

题目描述:

给出长度为 n n n的序列 a i a_i ai,选出最少的数(非空)使得它们的 g c d gcd gcd 1 1 1
n , a i ≤ 3 ∗ 1 0 5 n,a_i\le3*10^5 n,ai3105,无解输出 − 1 -1 1

题目分析:

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

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

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");
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值