[CF1043]F. Make It One——容斥原理

题目大意:

给定一个集合,要求你从中选出一些数使得他们的gcd为1,并且使选出的数最少。

思路:

假设最后的答案为x,那么不难发现,这x个数中任意选出x-1个数他们都有公共的因子,并且这些因子互不相同,于是可以得出答案最大为7。
考虑从小到大枚举答案,计算出每种因子d有多少数包含d这个因子,记为 c n t d cnt_d cntd
f i , j f_{i,j} fi,j为i个数gcd为j的方案数,从大到小枚举j,不难得到 f i , j = ( c n t j i ) − s u m j ∣ k , k ̸ = j f i , k f_{i,j}={cnt_{j}\choose i}-sum_{j|k,k\not=j}f_{i,k} fi,j=(icntj)sumjk,k̸=jfi,k
最后判断一下 f i , 1 f_{i,1} fi,1是否有解即可。
时间复杂度 a n s × O ( n ln ⁡ n ) ans\times O(n\ln n) ans×O(nlnn)

#include<bits/stdc++.h>

#define REP(i,a,b) for(int i=a,i##_end_=b;i<=i##_end_;++i)
#define DREP(i,a,b) for(int i=a,i##_end_=b;i>=i##_end_;--i)
#define debug(x) cout<<#x<<"="<<x<<endl
typedef long long ll;

using namespace std;

void File(){
	freopen("Conscience.in","r",stdin);
	freopen("Conscience.out","w",stdout);
}

template<typename T>void read(T &_){
	T __=0,mul=1; char ch=getchar();
	while(!isdigit(ch)){
		if(ch=='-')mul=-1;
		ch=getchar();
	}
	while(isdigit(ch))__=(__<<1)+(__<<3)+(ch^'0'),ch=getchar();
	_=__*mul;
}

const int maxn=3e5+10;
const ll mod=1e9+7;
int n,a[maxn],cnt[maxn],bin[maxn];
ll f[maxn],fac[maxn],ifac[maxn];

ll qpow(ll x,ll y){
	ll ret=1; x%=mod;
	while(y){
		if(y&1)ret=ret*x%mod;
		x=x*x%mod;
		y>>=1;
	}
	return ret;
}

void math_init(){
	fac[0]=1;
	REP(i,1,maxn-10)fac[i]=fac[i-1]*i%mod;
	ifac[maxn-10]=qpow(fac[maxn-10],mod-2);
	DREP(i,maxn-11,0)ifac[i]=ifac[i+1]*(i+1)%mod;
}

ll C(ll x,ll y){if(x<y)return 0;return fac[x]*ifac[y]%mod*ifac[x-y]%mod;}

int main(){
	File();
	math_init();
	read(n);
	REP(i,1,n)read(a[i]),++bin[a[i]];
	REP(i,1,maxn-10)for(int j=i;j<=maxn-10;j+=i)cnt[i]+=bin[j];
	REP(i,1,7){
		memset(f,0,sizeof(f));
		DREP(j,maxn-10,1){
			f[j]=C(cnt[j],i);
			for(int k=2*j;k<=maxn-10;k+=j)
				f[j]=(f[j]-f[k])%mod;
			//debug(j); cout<<f[j]<<endl;
		}
		if(f[1])return printf("%d\n",i),0;
	}
	puts("-1");
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值