LuoguP2257YY的GCD——莫比乌斯反演

//八中上的权限题,只能上洛谷拷了

题目描述

神犇YY虐完数论后给傻×kAc出了一题

给定N, M,求1<=x<=N, 1<=y<=M且gcd(x, y)为质数的(x, y)有多少对

kAc这种傻×必然不会了,于是向你来请教……

多组输入

输入输出格式

输入格式:
第一行一个整数T 表述数据组数

接下来T行,每行两个正整数,表示N, M

输出格式:
T行,每行一个整数表示第i组数据的结果

输入输出样例

输入样例
2
10 10
100 100
输出样例
30
2791
说明

T = 10000

N, M <= 10000000


这道题要求的是 ni=1mj=1[gcd(i,j)=p] ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = p ] p p 为质数),我们来推一下式子(我们假定n<m)
ni=1mj=1[gcd(i,j)=p]=pprimenpi=1mpj=1x|gcd(i,j)μ(x)=pprimenpx=1μ(x)[npx][mpx] ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = p ] = ∑ p ∈ p r i m e ∑ i = 1 n p ∑ j = 1 m p ∑ x | g c d ( i , j ) μ ( x ) = ∑ p ∈ p r i m e ∑ x = 1 n p μ ( x ) [ n p x ] [ m p x ]
原式的 px p x 确实让人不爽,而且对着这个式子直接做会T,所以我们还得继续推,我们令 T=px T = p x ,则原式
=nT=1p|T,pprimeμ(Tp)[nT][mT]=nT=1[nT][mT](p|T,pprimeμ(Tp)) = ∑ T = 1 n ∑ p | T , p ∈ p r i m e μ ( T p ) [ n T ] [ m T ] = ∑ T = 1 n [ n T ] [ m T ] ( ∑ p | T , p ∈ p r i m e μ ( T p ) )
前面的部分可以用数论分块直接搞,右边的东西我们可以预处理,我们用线性筛筛出素数,然后计算其倍数,最后统计一个前缀和即可(因为左边是分块,所以右边必须是前缀和的形式)
#include<bits/stdc++.h>
#define MAXN 10000000
#define ll long long
using namespace std;
ll read(){
    char c;ll x;while(c=getchar(),c<'0'||c>'9');x=c-'0';
    while(c=getchar(),c>='0'&&c<='9') x=x*10+c-'0';return x;
}
void print(ll x){
    if(x/10) print(x/10);
    putchar(x%10+'0');
}
int T,n,m,top,l,r,mu[MAXN+5],pri[MAXN+5],vis[MAXN+5];
ll ans,sum[MAXN+5],g[MAXN+5];
int main()
{
    T=read();mu[1]=1;
    register int i,j;
    for(i=2;i<=MAXN;i++){
        if(!vis[i]) pri[++top]=i,mu[i]=-1;
        for(j=1;j<=top&&pri[j]*i<=MAXN;j++){
            vis[pri[j]*i]=1;
            if(i%pri[j]==0) break;
            mu[i*pri[j]]=-mu[i];
        }
    }
    for(j=1;j<=top;j++)
     for(i=1;i*pri[j]<=MAXN;i++) g[i*pri[j]]+=(ll)mu[i];
    for(i=1;i<=MAXN;i++) sum[i]=sum[i-1]+g[i];
    while(T--){
        n=read();m=read();ans=0;
        if(n>m) swap(n,m);l=1;
        while(l<=n){
            r=min(n/(n/l),m/(m/l));r=min(r,n);
            ans+=1ll*(n/l)*(m/l)*(sum[r]-sum[l-1]);
            l=r+1;
        }
        print(ans);puts("");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值