原题链接:http://codeforces.com/contest/803/problem/F
题意:若gcd(a1, a2, a3,...,an)=1则认为这n个数是互质的。求集合a中,元素互质的集合的个数。
思路:首先知道一个大小为n的集合有2n-1个非空子集,运用容斥,对某个数,我们可以求出它作为因子出现的个数(假设为ki)。推一下式子,可以得到结果就等于:Σmiu[i]*(2i-1),其中miu[i]是莫比乌斯函数。
时间复杂度为:O(n*sqrt(max_a)),看起来似乎会超时,实际上用了不到300ms过了。
AC代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<map> 5 using namespace std; 6 typedef long long LL; 7 const LL MOD=1e9+7; 8 const int MAXN=1e5+10; 9 int num[MAXN]; 10 map<int, int> mp; 11 int miu[MAXN],primes[MAXN],tot=0; 12 bool isPrime[MAXN]; 13 void getMiu() 14 { 15 memset(isPrime,true,sizeof(isPrime)); 16 miu[1]=1; 17 for(int i=2;i<MAXN;i++) 18 { 19 if(isPrime[i]) 20 { 21 miu[i]=-1; 22 primes[++tot]=i; 23 } 24 for(int j=1;j<=tot;j++) 25 { 26 if(i*primes[j]>=MAXN) break; 27 isPrime[i*primes[j]]=false; 28 if(i%primes[j]==0) 29 { 30 miu[i*primes[j]]=0; 31 break; 32 } 33 miu[i*primes[j]]=-miu[i]; 34 } 35 } 36 } 37 LL POW[MAXN]; 38 void getpow() 39 { 40 POW[0]=1; 41 for(int i=1;i<MAXN;i++) 42 POW[i]=POW[i-1]*2%MOD; 43 return; 44 } 45 int main() 46 { 47 int n,a,maxx; 48 getMiu(); 49 getpow(); 50 scanf("%d", &n); 51 maxx=0; 52 for(int i=0;i<n;i++){ 53 scanf("%d", &a);//cout<<'*'<<endl; 54 maxx=max(a, maxx); 55 for(int j=1;j*j<=a;j++){ 56 if(a%j==0){ 57 mp[j]++; 58 if(j*j!=a) 59 mp[a/j]++; 60 } 61 } 62 } 63 64 LL res=0; 65 for(int i=1;i<=maxx;i++){ 66 if(mp[i]!=0){ 67 res=(res+miu[i]*(POW[mp[i]]-1))%MOD; 68 } 69 } 70 res=(res%MOD+MOD)%MOD; 71 cout<<res<<endl; 72 }
做过多校题HDU6053发现思路差不多,于是一发就AC了特别开心 :D