bzoj 1101 莫比乌斯反演

最裸的莫比乌斯

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define pii pair<int, int>

using namespace std;

const int N = 1e5 + 7;
const int M = 1e6 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 +7;

int p[N], is[N], mbs[N], sum[N], n, m, d, ans, tot;

void init(){
    memset(is, 1 ,sizeof(is));
    mbs[1]=1;
    for(int i = 2; i < N; i++) {
        if(is[i]){
            p[++tot] = i;
            mbs[i] = -1;
        }
        for(int j = 1; j <= tot && p[j] * i < N; j++){
            is[i * p[j]] = 0;
            if(i % p[j] == 0){
                mbs[i * p[j]] = 0;
                break;
            } else {
                mbs[i * p[j]] = -mbs[i];
            }
        }
    }
    for(int i = 1; i < N; i++) {
        sum[i] = mbs[i] + sum[i - 1]; //维护前缀和
    }
}

int cal(int n, int m){  //求[1,n][1,m]区间内互质的(x, y)的对数
    int ans=0;
    if(n > m) swap(n, m);
    for(int L = 1, R=0; L <= n; L = R + 1) {
        R = min(n / (n / L), m /(m / L));     // 分段加速
        ans += (sum[R] - sum[L - 1]) * (n / L) * (m / L);
    }
    return ans;
}

int main(){
    init();
    int T; scanf("%d", &T);
    while(T--) {
        scanf("%d%d%d",&n,&m,&d);
        ans = cal(n / d, m / d);
        printf("%d\n", ans);
    }
    return 0;
}
/*
*/

 

posted @ 2018-06-19 23:46  NotNight  阅读(140)  评论(0编辑  收藏  举报