前言
板题2号
题目
讲解
若求 (sum_{i=1}^nsum_{j=1}^m[gcd(i,j)=p]),其中 (p) 为定值
则 (f(k)=sum_{i=1}^{frac{min(n,m)}{p}}mu(i)lfloordfrac{n}{ip} floorlfloordfrac{m}{ip} floor)
现 (p) 为任意质数,即求 (sum_{pin prime}sum_{i=1}^{frac{min(n,m)}{p}}mu(i)lfloordfrac{n}{ip} floorlfloordfrac{m}{ip} floor)
换元后得到 (sum_{pin prime}sum_{p|t}mu(dfrac{t}{p})lfloordfrac{n}{t} floorlfloordfrac{m}{t} floor)
我们来枚举(t),得到 (sum_{t=1}^{min(n,m)}sum_{p|t}mu(dfrac{t}{p})lfloordfrac{n}{t} floorlfloordfrac{m}{t} floor)
把与 (p) 无关的两项提出来:
(sum_{t=1}^{min(n,m)}lfloordfrac{n}{t} floorlfloordfrac{m}{t} floorsum_{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),'
');
}
return 0;
}