【codeforces 803F】Coprime Subsequences

【题目链接】:http://codeforces.com/contest/803/problem/F

【题意】

给你一个序列;
问你这个序列里面有多少个子列;
且这个子列里面的所有数字互质;

【题解】

计算cnt[x];
表示数组里有多少个数是x的倍数;
则某个子列里面所有的数字都能被x整除的子列个数为2cnt[x]1
把这个值记为f[x];
则我们用需要用容斥原理;
把所有能被2,3,..n整除的子列删除掉;
这里面会有重复计数的问题;
解决方式是,从大到小枚举f[x]
然后对于y=i*x的
f[x]减去所有的f[y];
这样就能保证
在减掉
f[2]的时候,不会包括f[4]的方案;
最后剩下的就是互质的子列方案了;
f[x]在逆序更新过后;
实际上是gcd为x的子列的个数;
减去x的倍数的gcd;是为了减去那些gcd不为x的子列;
因为对于【全是x的倍数】的倍数的子列;它们的gcd并不为x;
UPD1:
写得更形式一点
f[i]=f[i]i|xf[x]
即逆着筛掉gcd不为i的子列;

【Number Of WA

0

【完整代码】

#include <bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define ms(x,y) memset(x,y,sizeof x)

typedef pair<int,int> pii;
typedef pair<LL,LL> pll;

const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
const double pi = acos(-1.0);
const int N = 1e5+100;
const LL MOD = 1e9+7;

int bo[N],n,f[N],ma;
LL po[N];

int main()
{
    //freopen("F:\\rush.txt","r",stdin);
    ios::sync_with_stdio(false),cin.tie(0);//scanf,puts,printf not use
    cin >> n;
    po[0] = 1;
    rep1(i,1,n)
        po[i] = (1LL*po[i-1]*2)%MOD;
    rep1(i,1,n)
    {
        int x;
        cin >> x;
        ma = max(ma,x);
        bo[x]++;
    }
    rep1(i,1,ma)
    {
        int ret = 0;
        for (int j = i;j<=ma;j+=i)
            ret+=bo[j];
        f[i] = po[ret]-1;
    }
    rep2(i,ma,1)
        for (int j = i+i;j<=ma;j+=i)
            f[i] = (f[i]-f[j]+MOD)%MOD;
    cout << f[1] << endl;
    return 0;
}
posted @ 2017-10-04 18:44  AWCXV  阅读(120)  评论(0编辑  收藏  举报