Codeforces 803F - Coprime Subsequences(数论)

原题链接: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

转载于:https://www.cnblogs.com/MasterSpark/p/7453520.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值