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");
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章