CodeForces 803F Coprime Subsequences 莫比乌斯,容斥
题意:给出一个序列,问有多少个 gcd 为 1 的子序列。
tags:考虑求出 gcd > 1 的子序列个数,再用 (2^n)-1 减去它即是答案。
枚举 gcd为 g,预处理出 a[] 的因子,然后看有多少个 a[] 是 g 的倍数,假设有 cnt 个,那就有 (2^cnt)-1 个子序列 gcd 为 g 。
但实际有重复,我们多计算了 gcd 为 g 的倍数的情况,所以直接莫比乌斯再去一下重就好了。
记: 最后输出加个 mod , 即 (ans+mod)%mod ,最后有可能是负数,又是这样挂了一发啊啊啊。。
#include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b; i>=a; --i) #define mes(a,b) memset(a,b,sizeof(a)) #define INF 0x3f3f3f3f #define MP make_pair #define PB push_back #define fi first #define se second typedef long long ll; const int N = 200005, mod = 1e9+7; int mu[N]; void Mobius(int mn) { mu[1]=1; for(int i=1; i<=mn; ++i) for(int j=i+i; j<=mn; j+=i) mu[j] -= mu[i]; } ll fpow(ll a, int b) { ll ans=1; for( ; b; b>>=1, a=a*a%mod) if(b&1) ans=ans*a%mod; return ans; } int n, a[N], cnt[N]; int main() { scanf("%d", &n); int mx=0; rep(i,1,n) { scanf("%d", &a[i]); mx = max(mx, a[i]); ++cnt[a[i]]; for(int j=2; j<=sqrt(a[i]); ++j) if(a[i]%j==0) { ++cnt[j]; if(j!=a[i]/j) ++cnt[a[i]/j]; } } Mobius(mx); ll ans=0; rep(i,2,mx) if(mu[i]) { ( ans += (fpow(1LL*2, cnt[i])-1)*-mu[i] ) %= mod; } printf("%lld\n", ( fpow(1LL*2, n)-1-ans +mod )%mod ); return 0; }