[CF1043]F. Make It One——容斥原理
题目大意:
给定一个集合,要求你从中选出一些数使得他们的gcd为1,并且使选出的数最少。
思路:
假设最后的答案为x,那么不难发现,这x个数中任意选出x-1个数他们都有公共的因子,并且这些因子互不相同,于是可以得出答案最大为7。
考虑从小到大枚举答案,计算出每种因子d有多少数包含d这个因子,记为\(cnt_d\)。
设\(f_{i,j}\)为i个数gcd为j的方案数,从大到小枚举j,不难得到\(f_{i,j}={cnt_{j}\choose i}-sum_{j|k,k\not=j}f_{i,k}\)。
最后判断一下\(f_{i,1}\)是否有解即可。
时间复杂度\(ans\times O(n\ln n)\)。
#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;
}