数论-莫比乌斯-hdu1695 GCD

给定b,d,k,[1,b],[1,d]中取x,y,求gcd(x,y) = k的(x,y)对数

ps:(1,2)和(2,1)相同

简化为gcd(x / k,y / k) = 1

gcd(x,y) = 1,x,y范围为[1,b / k],[1,d / k]

1.欧拉函数+容斥

2.莫比乌斯

大佬题解

https://www.cnblogs.com/iiyiyi/p/5635303.html

1.欧拉函数+容斥

#include <iostream>

#include <cstdio>

#include <cstring>

#include <cmath>

#include <vector>

using namespace std;

const int maxn = 1e5 + 5;

typedef long long ll;

int a,b,c,d,k;

ll phi[maxn];

int fac[15],num = 0;


void init()

{

    for (int i = 2; i < maxn; i ++) {

        if(phi[i] == 0){

            for (int j = i; j < maxn; j += i) {

                if(phi[j] == 0) phi[j] = j;

                phi[j] = phi[j] / i * (i - 1);

            }

        }

    }

    phi[1] = 1;

    for (int i = 2; i < maxn; i ++) {

        phi[i] += phi[i - 1];

    }

}


void divide(int y)

{

    num = 0;

    for (int i = 2; i <= sqrt(0.5 + y); i ++) {

        if(y % i == 0){

            fac[num ++] = i;

            while(y % i == 0) y/= i;

        }

    }

    if(y > 1) fac[num++] = y;

}

ll solve(int b)//质因子分解可以打表

{

    ll ans = 0;

    for (int i = 1; i < (1 << num); i ++) {

        int t = i,cnt = 0;

        ll lcm = 1;

        for (int j = 0; j < num; j ++) {

            if(t & 1){lcm *= fac[j];cnt ++;}

            t >>= 1;

            if(t == 0) break;

        }

        if(cnt & 1) ans += b / lcm;

        else ans -= b / lcm;

    }

    return ans;

}

int main()

{

    init();


    int T;scanf("%d",&T);

    for (int cn = 1; cn <= T; cn ++) {

        scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);

        //k = 0?

        if(k == 0){ printf("Case %d: 0\n",cn);continue;}

        b /= k;d /= k;

        if(b > d) swap(b, d);

        ll ans = phi[b];

       //[b + 1,d]

        for (int i = b + 1; i <= d; i ++) {

            divide(i);

            ans += b- solve(b);

        }

        printf("Case %d: %lld\n",cn,ans);

    }

    return 0;

}

2.莫比乌斯

#include <cstdio>

#include <iostream>

#include <cstring>

#include <cmath>

using namespace std;

typedef long long ll;

const int maxn = 1e5 + 5;

int mo[maxn];

bool isprime[maxn];

int prime[maxn / 10],sz = 0;


int a,b,c,d,k;


void init()

{

    for (int i = 2; i < maxn; i ++) {

        if(isprime[i] == 0){

            prime[sz ++] = i;

            mo[i] = -1;

        }

        for (int j = 0; j < sz && prime[j] * i < maxn; j ++) {

            isprime[i * prime[j]] = 1;

            if(i % prime[j] == 0) break;

            else mo[i * prime[j]] = -mo[i];

        }

    }

    mo[1] = 1;

}

int main()

{

    init();

    int T;scanf("%d",&T);

    for (int cn = 1; cn <= T; cn ++) {

        scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);

        if(k == 0){printf("Case %d: 0\n",cn);continue;}

        b /= k;d /= k;

        int t = min(b,d);

        ll ans1 = 0,ans2 = 0;

        for (int i = 1; i <= t; i ++) {

            ans1 += (ll)mo[i] * (b / i) * (d / i);

        }

        for (int i = 1; i <= t; i ++) {

            ans2 += (ll)mo[i] * (t / i) * (t / i);

        }

       printf("Case %d: %lld\n",cn,ans1 - ans2 / 2);

    }

    return 0;

}


猜你喜欢

转载自blog.csdn.net/sm_545/article/details/81037545