【容斥+素数】 HDU 2841 Visible Trees

通道

题意:求一个区间[1,m]内与i的互质的数的个数。这里1<=i<=n,

思路:对i分解质因子然后容斥

代码:

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

typedef long long LL;

const int maxn = 100010;

LL ans;
int n,m;
int fac[maxn];
int prime[maxn];
int facCnt;

void getPrime() {
    bool flag[maxn];
    memset(flag,false,sizeof(flag));
    prime[0] = 0;
    for(int i = 2; i < maxn; i++) {
        if(flag[i] == false) prime[++prime[0]] = i;
        for(int j = 1; j <= prime[0]&&i*prime[j]<maxn; j++) {
            flag[i*prime[j]] = true;
            if(i % prime[j] == 0)
                break;
        }
    }
}

void getFac(int num) {
    int tmp = num;
    facCnt = 0;
    for(int i = 1; i <= prime[0] && prime[i]*prime[i] <= tmp; i++) {
        if(tmp % prime[i] == 0) {
            fac[facCnt++] = prime[i];
            while(tmp%prime[i] == 0) tmp /= prime[i];
        }
        if(tmp == 1) break;
    }
    if(tmp > 1) fac[facCnt++] = tmp;
}

LL solve(int m) {
    int que[110];
    int l = 0;
    que[l++] = 1;
    for(int i = 0; i < facCnt; i++) {
        int k = l;
        for(int j = 0; j < k; j++)
            que[l++] = fac[i]*que[j]*(-1);
    }
    LL anw = 0;
    for(int i = 0; i < l; i++)
        anw += m/que[i];
    return anw;
}

int main() {
    int test;getPrime(); 
    scanf("%d",&test);
    for(int item = 1; item <= test; item++) {
        scanf("%d %d",&n,&m);
        if(n > m) std::swap(n,m);
        ans = 0;
        for(int i = 1; i <= n; i++) {
            getFac(i);
            ans += solve(m);
        }
        printf("%I64d\n",ans);
    }
    return 0;
}
View Code

 

posted @ 2015-08-02 19:15  mithrilhan  阅读(167)  评论(0编辑  收藏  举报