【HDU1695】GCD(莫比乌斯反演+容斥)

记录一个菜逼的成长。。

题目链接
题目大意:
问x在[1,a],y在[1,b],有多少无序对gcd(x,y) == k

首先将范围缩小到[1,a/k]或[1,b/k]
要比较哪个范围较小,因为gcd(x,y)最大为k的min(a/k,b/k)倍
先求出所有的种数,然后再减去重复的

#include <bits/stdc++.h>
using namespace std;
#define cl(a,b) memset(a,b,sizeof(a))
typedef long long LL;
const int maxn = 100000 + 10;
bool check[maxn];
int mu[maxn],prime[maxn];
void Mobius()
{
    cl(check,false);
    mu[1] = 1;
    int tot = 0;
    for( int i = 2; i < maxn; i++ ){
        if(!check[i]){
            prime[tot++] = i;
            mu[i] = -1;
        }
        for( int j = 0; j < tot; j++ ){
            if(i * prime[j] >= maxn)break;
            check[i*prime[j]] = true;
            if(i % prime[j] == 0){
                mu[i * prime[j]] = 0;
                break;
            }
            else {
                mu[i * prime[j]] = -mu[i];
            }
        }
    }
}
int main()
{
    Mobius();
    int T,cas = 1;scanf("%d",&T);
    while(T--){
        int a,b,c,d,k;
        scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
        if(!k){
            printf("Case %d: 0\n",cas++);
            continue;
        }
        b /= k;
        d /= k;
        LL ans1 = 0,ans2 = 0;
        if(b > d)swap(b,d);
        for( int i = 1; i <= b; i++ ){
            ans1 += (LL)mu[i] * (b/i) * (d/i);
        }
        for( int i = 1; i <= b; i++ ){
            ans2 += (LL)mu[i] * (b/i) * (b/i);
        }
        printf("Case %d: %lld\n",cas++,ans1-ans2/2);//减去x,y都在[1,b/k]的种数,因为跟顺序无关,还要除以2
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值