[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;
}

转载于:https://www.cnblogs.com/ylsoi/p/9904101.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值