CodeForce1043F 隐晦的因子容斥,需要注意到答案t在1~8之间 维护dp[j]:n个数取t个数gcd为j的方案数 //CF1043F题意:n个数选尽量少的数使得gcd为1 n,ai<=3e5 如果没有输出-1 //思路://首先,如果答案存在,那么最多为7(因为前7个质数乘起来>=3e5)//问题转化成n个数取i个数gcd为1的方案数不为0 的最小的i //考虑DP[i][j] n个数选i个数gcd为j的方案数 //子集选取gcd为j,考虑因子容斥 //dp[i][j]-=dp[i][j*k] ,k>=2 初始dp[i][j]=C(cnt[j],i);//问题变成找到最小的i使得dp[i][1]>0//i从小到大枚举检测即可 #include<bits/stdc++.h>#define ll long longusing namespace std;const int mod=1e9+7; int a[300005];ll dp[10][300005];int cnt[300005];int jc[300005];int jv[300005];ll qmod(ll a,ll b){ll res=1;while(b){if(b&1)res=res*a%mod;a=a*a%mod;b=b>>1;}return res;} ll getC(ll a,ll b){if(a<b)return 0;return 1ll*jc[a]*jv[b]%mod*jv[a-b]%mod;}int main(){jc[0]=jv[0]=1;for(int i=1;i<=300000;i++)jc[i]=1ll*jc[i-1]*i%mod,cnt[i]=0;jv[300000]=qmod(jc[300000],mod-2);for(int i=299999;i>=1;i--)jv[i]=1ll*jv[i+1]*(i+1)%mod;int n;scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",&a[i]),cnt[a[i]]++;for(int i=1;i<=300000;i++){for(int j=2*i;j<=300000;j+=i)cnt[i]+=cnt[j];}for(int i=1;i<=8;i++){for(int j=300000;j>=1;j--){dp[i][j]=getC(cnt[j],i);for(int k=2*j;k<=300000;k+=j)dp[i][j]=(dp[i][j]-dp[i][k]+mod)%mod;}if(dp[i][1]>0){printf("%dn",i);return 0;}}//5 7 2 4 4 4//printf("test:%d %d %d %dn",dp[2][1],dp[2][2],dp[2][4],dp[2][8]); puts("-1");} CodeForce803F 经典的因子容斥 //CF803F 因子容斥 n<=1e5,ai<=1e5 //题意:问有多少个子集S满足gcd(S)==1 //思路:设dp[j]为 子集的gcd恰好是j的个数//现在求 dp[1] //cnt[j]表示有多少个ak满足ak是j的倍数//在cnt[j]里取任意个都是满足要求的子集 //C(cnt[j],1)+C(cnt[j],2)+... C(cnt[j],cnt[j]) =2^cnt[j]-1//初始化dp[j]=2^cnt[j]-1,此时dp[j]表示子集的gcd是j的倍数的个数//我们要求恰好为j的个数,因子容斥即可 //一开始想设dp[i][j]为n个选i个gcd为j的方案数//但是Wa13了才发现i可以取很大#include<bits/stdc++.h>#define ll long longusing namespace std;const int mod=1e9+7;int cnt[100005];int a[100005];ll dp[100005];ll jc[100005];ll jv[100005];//ll getc(ll a,ll b)//{//if(a<b)return 0;//return 1ll*jc[a]*jv[b]%mod*jv[a-b]%mod;//}ll qmod(ll a,ll b){ll res=1;while(b){if(b&1)res=res*a%mod;a=a*a%mod;b=b>>1;}return res;}int main(){//jc[0]=jv[0]=1;//for(int i=1;i<=100000;i++)jc[i]=jc[i-1]*i%mod;//jv[100000]=qmod(jc[100000],mod-2);//for(int i=99999;i>=1;i--)jv[i]=jv[i+1]*(i+1)%mod;int n;scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",&a[i]),cnt[a[i]]++;for(int i=1;i<=100000;i++){for(int j=2*i;j<=100000;j+=i)cnt[i]+=cnt[j];}ll ans=0;//for(int i=1;i<=60;i++)//{//for(int j=100000;j>=1;j--)//{//dp[i][j]=getc(cnt[j],i);//for(int k=2*j;k<=100000;k+=j)//dp[i][j]=(dp[i][j]-dp[i][k]+mod)%mod;//}//ans=(ans+dp[i][1])%mod;//}for(int j=100000;j>=1;j--){dp[j]=(qmod(2,cnt[j])-1+mod)%mod;for(int k=2*j;k<=100000;k+=j){dp[j]=(dp[j]-dp[k]+mod)%mod;}}ans=(ans+dp[1])%mod;printf("%I64dn",ans%mod);}