【莫比乌斯】BZOJ 2818 Gcd

通道

题意:给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的数对(x,y)有多少对

思路:类似HDU 1695

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

typedef long long ll;

template <class T>
inline bool rd(T &ret) {
    char c; int sgn;
    if(c = getchar() , c == EOF) return false;
    while(c != '-' && (c < '0' || c > '9')) c = getchar();
    sgn = (c == '-') ? -1 : 1;
    ret = (c == '-') ? 0 : (c - '0');
    while(c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
    ret *= sgn;
    return true;
}

const int MAX_N = 10000007;

bool vis[MAX_N];
int pcnt;
int cnt[MAX_N], mu[MAX_N], prime[MAX_N];

void Mobius(int n) {
    pcnt = 0;
    vis[1] = mu[1] = 1;
    for(int i = 1;i <= n; i++)  mu[i] = 1;
    for(int i = 2;i <= n; i++) {
        if(!vis[i]) {
            prime[pcnt++] = i;
            for(int j = i;j <= n;j += i) {
                vis[j] = 1;
                mu[j] *= -1;
                if((j/i) % i == 0)  mu[j] = 0;
                int t = j;
                while(t % i == 0) t /= i, cnt[j]++;
            }
        }
    }
}

int n;

int main() {
    rd(n);
    Mobius(n);
    ll ans = 0;
    for (int i = 0; i < pcnt && prime[i] <= n; ++i) {
        int m = n / prime[i];
        for (int i = 1; i <= m; ++i) ans += (ll) mu[i] * (m / i) * (m / i);
    }
    printf("%lld\n", ans);
    return 0;
}
View Code

 

posted @ 2015-08-17 21:41  mithrilhan  阅读(148)  评论(0编辑  收藏  举报