莫比乌斯反演 - YY的GCD - 洛谷 P2257

莫比乌斯反演 - YY的GCD - 洛谷 P2257

题意:

给 定 N , M , 求 1 ≤ x ≤ N , 1 ≤ y ≤ M 且 gcd ⁡ ( x , y ) 为 质 数 的 ( x , y ) 有 多 少 对 。 给定 N,M,求 1 \leq x \leq N,1 \leq y \leq M 且 \gcd(x, y)为质数的 (x, y)有多少对。 N,M1xN1yMgcd(x,y)(x,y)

输入格式

第一行一个整数 T 表述数据组数。

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

输出格式

T 行,每行一个整数表示第 i 组数据的结果。

输入输出样例
输入

2
10 10
100 100

输出

30
2791

说明/提示

T ≤ 1 0 4 , N , M ≤ 1 0 7 。 T \le 10^4,N, M \leq 10^7。 T104N,M107


分析:

设 f ( d ) 为 满 足 g c d ( i , j ) = d 的 数 对 的 个 数 , F ( n ) 为 满 足 g c d ( i , j ) 是 n 的 倍 数 的 数 对 的 个 数 。 即 : 设f(d)为满足gcd(i,j)=d的数对的个数,F(n)为满足gcd(i,j)是n的倍数的数对的个数。即: f(d)gcd(i,j)=dF(n)gcd(i,j)n

f ( d ) = ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = d ] f(d)=\sum_{i=1}^{n}\sum_{j=1}^m[gcd(i,j)=d] f(d)=i=1nj=1m[gcd(i,j)=d]

F ( n ) = ∑ n ∣ d f ( d ) = ⌊ N n ⌋ ⋅ ⌊ M n ⌋ F(n)=\sum_{n|d}f(d)=\lfloor\frac{N}{n}\rfloor·\lfloor\frac{M}{n}\rfloor F(n)=ndf(d)=nNnM

根 据 反 演 定 理 : f ( n ) = ∑ n ∣ d μ ( ⌊ d n ⌋ ) F ( d ) 根据反演定理:f(n)=\sum_{n|d}\mu(\lfloor\frac{d}{n}\rfloor)F(d) :f(n)=ndμ(nd)F(d)

A n s = ∑ p ∈ p r i m e ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = p ] = ∑ p ∈ p r i m e f ( p ) Ans=\sum_{p∈prime}\sum_{i=1}^{n}\sum_{j=1}^m[gcd(i,j)=p]=\sum_{p∈prime}f(p) Ans=pprimei=1nj=1m[gcd(i,j)=p]=pprimef(p)

下 面 化 简 A n s : 下面化简Ans: Ans

我 们 枚 举 倍 数 d , 我们枚举倍数d, d

A n s = ∑ p ∈ p r i m e f ( p ) = ∑ p ∈ p r i m e ∑ d = 1 m i n ( ⌊ n p ⌋ , ⌊ m p ⌋ ) μ ( d ) F ( d p ) = ∑ p ∈ p r i m e ∑ d = 1 m i n ( ⌊ n p ⌋ , ⌊ m p ⌋ ) μ ( d ) ⌊ n d p ⌋ ⌊ m d p ⌋ Ans=\sum_{p∈prime}f(p)=\sum_{p∈prime}\sum_{d=1}^{min(\lfloor\frac{n}{p}\rfloor,\lfloor\frac{m}{p}\rfloor)}\mu(d)F(dp)=\sum_{p∈prime}\sum_{d=1}^{min(\lfloor\frac{n}{p}\rfloor,\lfloor\frac{m}{p}\rfloor)}\mu(d)\lfloor\frac{n}{dp}\rfloor\lfloor\frac{m}{dp}\rfloor Ans=pprimef(p)=pprimed=1min(pn,pm)μ(d)F(dp)=pprimed=1min(pn,pm)μ(d)dpndpm

令 T = d ⋅ p , 即 T 是 p 的 倍 数 令T=d·p,即T是p的倍数 T=dpTp

A n s = ∑ T = 1 m i n ( n , m ) ⌊ n T ⌋ ⌊ m T ⌋ ∑ p ∣ T ,   p ∈ p r i m e μ ( T p ) Ans=\sum_{T=1}^{min(n,m)}\lfloor\frac{n}{T}\rfloor\lfloor\frac{m}{T}\rfloor\sum_{p|T,\ p∈prime}\mu(\frac{T}{p}) Ans=T=1min(n,m)TnTmpT, pprimeμ(pT)

到 这 里 , 我 们 就 能 够 计 算 出 答 案 了 。 需 要 预 处 理 几 个 数 组 : 到这里,我们就能够计算出答案了。需要预处理几个数组:

对 于 每 个 质 数 p , 我 们 枚 举 它 的 倍 数 T , 对于每个质数p,我们枚举它的倍数T, pT

对 于 每 一 个 T , 我 们 需 要 计 算 ∑ p ∣ T ,   p ∈ p r i m e μ ( T p ) , 即 T 的 所 有 质 因 数 的 倍 数 ( T / p ) 莫 比 乌 斯 函 数 的 和 。 对于每一个T,我们需要计算\sum_{p|T,\ p∈prime}\mu(\frac{T}{p}),即T的所有质因数的倍数(T/p)莫比乌斯函数的和。 TpT, pprimeμ(pT)T(T/p)

所 以 我 们 预 处 理 数 组 g 。 则 : g [ T ] = ∑ p ∣ T ,   p ∈ p r i m e μ ( T p ) 。 时 间 复 杂 度 O ( n l o g n ⋅ l o g n ) = O ( n ) 所以我们预处理数组g。则:g[T]=\sum_{p|T,\ p∈prime}\mu(\frac{T}{p})。时间复杂度O(\frac{n}{logn}·logn)=O(n) g:g[T]=pT, pprimeμ(pT)O(lognnlogn)=O(n)

由 于 前 一 部 分 需 要 整 除 分 块 , 我 们 还 需 要 快 速 计 算 每 一 块 的 数 组 g 的 和 , 由于前一部分需要整除分块,我们还需要快速计算每一块的数组g的和, g

所 以 , 我 们 再 对 数 组 g 求 前 缀 和 。 所以,我们再对数组g求前缀和。 g

最 后 结 合 整 除 分 块 能 够 计 算 答 案 。 最后结合整除分块能够计算答案。

时 间 复 杂 度 : O ( n + T n ) 时间复杂度:O(n+T\sqrt{n}) O(n+Tn )

代码:

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

#define ll long long

using namespace std;

const int N = 1e7+10;

int primes[N], mu[N], cnt;
ll g[N], sum[N];
bool st[N];
int T, n, m;

void get_prime(int n)
{
    mu[1]=1;
    for(int i=2;i<=n;i++)
    {
        if(!st[i])
        {
            primes[cnt++]=i;
            mu[i]=-1;
        }
        for(int j=0;primes[j]*i<=n;j++)
        {
            int p=primes[j];
            st[i*p]=true;
            if(i%p==0)
            {
                mu[i*p]=0;
                break;
            }
            mu[i*p]=-mu[i];
        }
    }
    for(int i=0;i<cnt;i++)
    {
        int p=primes[i];
        for(int T=p;T<=n;T+=p)
            g[T]+=mu[T/p];
    }
    for(int i=1;i<=n;i++) sum[i]=sum[i-1]+g[i];
}

ll cal(int a, int b)
{
    int n=min(a,b);
    ll res=0;
    for(int l=1, r;l<=n;l=r+1)
    {
        r=min(a/(a/l), b/(b/l));
        r=min(n,r);
        res+=(ll)(a/l)*(b/l)*(sum[r]-sum[l-1]);
    }
    return res;
}

int main()
{
    get_prime(N-1);
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        printf("%lld\n",cal(n,m));
    }
    
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值