hdu 1695 GCD (莫比乌斯反演)

题意:给你两个区间,区间的左端点式1,然后让你求有多少对数来自两个区间,然后他们的GCD为k;

思路:我们找两个数x,y的GCD为k,分别除以k后,相当于找x,y互质的个数,

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long LL;
int mu[1<<20];
LL n;
bool check[1<<20];
int prime[1<<20];

void Moblus()
{
    memset(check,false,sizeof(check));
    mu[1]=1;
    int tot=0;
    for(int i=2;i<=(1<<20);i++){
        if(!check[i]){
            prime[tot++]=i;
            mu[i]=-1;
        }
        for(int j=0;j<tot;j++){
            if(i*prime[j]>(1<<20)) 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()
{
    int T;
    scanf("%d",&T);
    Moblus();
    int cas=1;
    while(T--){
        int a,b,c,d,k;
        scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
        if(k==0){
            printf("Case %d: 0\n",cas++);continue;
        }
        if(b>d)swap(b,d);
        b/=k;d/=k;
        LL ans=0;
        for(int i=1;i<=b;i++){
            ans+=(LL)mu[i]*(b/i)*(d/i);
        }
        LL cnt=0;
        for(int i=1;i<=b;i++){
            cnt+=(LL)mu[i]*(b/i)*(b/i);
        }
        printf("Case %d: %lld\n",cas++,ans-cnt/2);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/lalalatianlalu/p/9125363.html