[洛谷P2257] YY的GCD
前言
板题2号
题目
讲解
若求 \(\sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)=p]\),其中 \(p\) 为定值
则 \(f(k)=\sum_{i=1}^{\frac{\min(n,m)}{p}}\mu(i)\lfloor\dfrac{n}{ip}\rfloor\lfloor\dfrac{m}{ip}\rfloor\)
现 \(p\) 为任意质数,即求 \(\sum_{p\in prime}\sum_{i=1}^{\frac{\min(n,m)}{p}}\mu(i)\lfloor\dfrac{n}{ip}\rfloor\lfloor\dfrac{m}{ip}\rfloor\)
换元后得到 \(\sum_{p\in prime}\sum_{p|t}\mu(\dfrac{t}{p})\lfloor\dfrac{n}{t}\rfloor\lfloor\dfrac{m}{t}\rfloor\)
我们来枚举\(t\),得到 \(\sum_{t=1}^{\min(n,m)}\sum_{p|t}\mu(\dfrac{t}{p})\lfloor\dfrac{n}{t}\rfloor\lfloor\dfrac{m}{t}\rfloor\)
把与 \(p\) 无关的两项提出来:
\(\sum_{t=1}^{\min(n,m)}\lfloor\dfrac{n}{t}\rfloor\lfloor\dfrac{m}{t}\rfloor\sum_{p|t}\mu(\dfrac{t}{p})\)
令 \(s(t)=\sum_{p|t}\mu(\dfrac{t}{p})\)
预处理 \(s\) 即可
代码
int mu[MAXN],prime[MAXN],pn,s[MAXN];
bool vis[MAXN];
void sieve(int x)
{
mu[1] = 1;
for(int i = 2;i <= x;++ i)
{
if(!vis[i]) prime[++pn] = i,mu[i] = -1;
for(int j = 1;j <= pn && i * prime[j] <= x;++ j)
{
vis[i * prime[j]] = 1;
if(i % prime[j] == 0) break;
mu[i * prime[j]] = -mu[i];
}
}
for(int i = 1;i <= pn;++ i)
for(int j = prime[i];j <= x;j += prime[i])
s[j] += mu[j / prime[i]];
for(int i = 1;i <= x;++ i) s[i] += s[i-1];
}
LL solve(int x,int y)
{
if(x > y) swap(x,y);
LL ret = 0;
for(int l = 1,r;l <= x;l = r+1)
{
r = Min(x/(x/l),y/(y/l));
ret += 1ll * (s[r] - s[l-1]) * (x/l) * (y/l);
}
return ret;
}
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
sieve(10000019);
for(int T = Read(); T ;-- T)
{
n = Read(); m = Read();
Put(solve(n,m),'\n');
}
return 0;
}