莫比乌斯反演 - 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,M,求1≤x≤N,1≤y≤M且gcd(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。 T≤104,N,M≤107。
分析:
设 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)=d的数对的个数,F(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=1n∑j=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)=∑n∣df(d)=⌊nN⌋⋅⌊nM⌋
根 据 反 演 定 理 : f ( n ) = ∑ n ∣ d μ ( ⌊ d n ⌋ ) F ( d ) 根据反演定理:f(n)=\sum_{n|d}\mu(\lfloor\frac{d}{n}\rfloor)F(d) 根据反演定理:f(n)=n∣d∑μ(⌊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=p∈prime∑i=1∑nj=1∑m[gcd(i,j)=p]=p∈prime∑f(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=p∈prime∑f(p)=p∈prime∑d=1∑min(⌊pn⌋,⌊pm⌋)μ(d)F(dp)=p∈prime∑d=1∑min(⌊pn⌋,⌊pm⌋)μ(d)⌊dpn⌋⌊dpm⌋
令 T = d ⋅ p , 即 T 是 p 的 倍 数 令T=d·p,即T是p的倍数 令T=d⋅p,即T是p的倍数
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=1∑min(n,m)⌊Tn⌋⌊Tm⌋p∣T, p∈prime∑μ(pT)
到 这 里 , 我 们 就 能 够 计 算 出 答 案 了 。 需 要 预 处 理 几 个 数 组 : 到这里,我们就能够计算出答案了。需要预处理几个数组: 到这里,我们就能够计算出答案了。需要预处理几个数组:
对 于 每 个 质 数 p , 我 们 枚 举 它 的 倍 数 T , 对于每个质数p,我们枚举它的倍数T, 对于每个质数p,我们枚举它的倍数T,
对 于 每 一 个 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)莫比乌斯函数的和。 对于每一个T,我们需要计算∑p∣T, p∈primeμ(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]=∑p∣T, p∈primeμ(pT)。时间复杂度O(lognn⋅logn)=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;
}