scau 18087 开始我是拒接的 mobius

其实有一个很有用的技巧就是,把gcd = 4的贡献,压去gcd = 2时的贡献,就不需要考虑这么多的了。

为什么可以把gcd = 4的,压去gcd = 2的呢,gcd = 12的,压去gcd = 6的去算呢,

其实这就是mobius的容斥原理,mu[4] = 0,mu[12] = 0,

例如:

http://www.cnblogs.com/liuweimingcprogram/p/6818754.html

 

这题的思路是,把每个数字都质因数分解,比如分解成12 = 2 * 3

然后暴力枚举每个质因子选or不选,就能知道,12的所有因子,

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;


#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <bitset>
const int maxn = 100000 + 20;
int prime[maxn][12];
void initPrime() {
    int mx = 0;
    for (int i = 2; i <= maxn - 20; ++i) {
        if (prime[i][0]) continue;
        for (int j = i; j <= maxn - 20; j += i) {
            prime[j][++prime[j][0]] = i;
//            mx = max(mx, prime[j][0]);
        }
    }
}
int num[maxn];
void init(int val) {
    int en = (1 << prime[val][0]) - 1;
    for (int i = 1; i <= en; ++i) {
        int t = 1;
        for (int j = 1; j <= prime[val][0]; ++j) {
            if (i & (1 << (j - 1))) {
                t *= prime[val][j];
            }
        }
        num[t]++;
    }
}
int calc(int val) {
    int ans = 0;
    int en = (1 << prime[val][0]) - 1;
    for (int i = 1; i <= en; ++i) {
        int t = 1;
        int cnt = 0;
        for (int j = 1; j <= prime[val][0]; ++j) {
            if (i & (1 << (j - 1))) {
                t *= prime[val][j];
                cnt++;
            }
        }
        if (cnt & 1) ans += num[t];
        else ans -= num[t];
    }
    return ans;
}
void work() {
//    int out = 3 * 5 * 7;
//    for (int i = 1; i <= prime[out][0]; ++i) {
//        printf("%d ", prime[out][i]);
//    }
    int n, q;
    scanf("%d%d", &n, &q);
    for (int i = 1; i <= n; ++i) {
        int val;
        scanf("%d", &val);
        init(val);
    }
    for (int i = 1; i <= q; ++i) {
        int val;
        scanf("%d", &val);
        printf("%d\n", n - calc(val));
    }
}

int main() {
#ifdef local
    freopen("data.txt", "r", stdin);
//    freopen("data.txt", "w", stdout);
#endif
    initPrime();
    work();
    return 0;
}
View Code

 

posted on 2017-05-29 23:52  stupid_one  阅读(394)  评论(0编辑  收藏  举报

导航