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

探讨了在特定约束条件下,如何通过枚举答案个数并利用容斥原理或莫比乌斯反演来求解最小数目的序列元素,使它们的GCD等于1的问题。分析了质因数在解决方案中的关键作用,以及如何通过复杂度为O(nlnn*7)的算法高效求解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述:

给出长度为 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");
}
### 关于Codeforces中的GCD问题 在Codeforces平台上存在多个涉及最大公约数(GCD)概念的问题。其中一道具有代表性的题目是编号为1025B的“Weakened Common Divisor”,该题由著名数学家Ildar引入了一个新的概念——弱化公因数(WCD),即对于一系列整数对列表而言的一种特殊性质[^2]。 具体到这道题目的描述如下:给出一个长度为\(n\)的数组\(a\),目标是在所有元素上加上同一个常量\(d\)之后能够找到至少两个不同的位置其值的最大公约数大于等于2,并且要使这个加上的常量尽可能小。此题的关键在于通过计算相邻两数之差来间接获取可能存在的公共因子,进而利用这些信息推导出满足条件所需的最小增量\[d\][^4]。 为了高效解决这类基于GCD的问题,在算法设计方面通常会采用一些特定技巧: - **差分遍历**:通过对原始序列做适当变换简化问题结构; - **快速求解GCD**:借助欧几里得算法迅速定位潜在候选者; - **优化查找过程**:针对所得结果进一步筛选最优方案; 下面是一个Python版本的解决方案片段用于演示如何处理上述提到的任务逻辑: ```python from math import gcd from itertools import pairwise def min_operations_to_weak_gcd(nums): diff_gcd = 0 for prev, curr in pairwise(nums): diff_gcd = gcd(diff_gcd, abs(curr - prev)) if diff_gcd == 1: return -1 factors = get_factors(diff_gcd) result = float('inf') target_modulo = nums[0] % diff_gcd for factor in factors: candidate = ((target_modulo + diff_gcd - (nums[0] % factor)) % factor) result = min(result, candidate) return int(result) def get_factors(n): """Helper function to generate all divisors.""" res = [] i = 1 while i*i <= n: if n % i == 0: res.append(i) if i != n // i: res.append(n//i) i += 1 return sorted(res)[::-1] ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值