题意:5e4组询问 给定a,b,d求$$ sum_{i=1}{a}sum_{j=1}{b}[gcd(i,j) = d]$$
题解:套路
[fleft ( d
ight ) = sum_{i=1}^{a}sum_{j=1}^{b}[gcd(i,j) = d]
]
[Fleft ( n
ight )=sum_{d|n} f(d) = left lfloor frac{a}{n}
ight
floorleft lfloor frac{b}{n}
ight
floor
]
[f(d) = sum_{d|n}mu(frac{n}{d})F(n) = sum_{d|n}mu(frac{n}{d})left lfloor frac{a}{n}
ight
floor left lfloor frac{b}{n}
ight
floor
]
然后令t = n/d
[f(d) = sum_{t=1}^{min(left lfloor frac{a}{d}
ight
floor,left lfloor frac{b}{d}
ight
floor)}mu(t)left lfloor frac{a}{dt}
ight
floorleft lfloor frac{b}{dt}
ight
floor
]
然后整除分块一下 筛出莫比乌斯函数的前缀和 做一个是根号n的复杂度
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
bool vis[50005];
int prim[50005];
int mu[50005];
int sum[50005];
int cnt;
void get_mu(int n)
{
mu[1] = 1;
for(int i = 2; i <= n; i++)
{
if(!vis[i])
{
mu[i] = -1;
prim[++cnt] = i;
}
for(int j = 1; j <= cnt && i * prim[j] <= n; j++)
{
vis[i * prim[j]] = 1;
if(i % prim[j] == 0) break;
else mu[i * prim[j]] -= mu[i];
}
}
for(int i = 1; i <= n; i++) sum[i] = sum[i - 1] + mu[i];
}
int main()
{
get_mu(50000);
int T;
scanf("%d", &T);
while(T--)
{
int a, b, d;
scanf("%d%d%d", &a, &b, &d);
ll ans = 0;
int len = min(a / d, b / d);
for(int l = 1, r; l <= len; l = r + 1)
{
int f1 = a / d;
int f2 = b / d;
r = min(f1 / (f1 / l), f2 / (f2 / l));
ans += 1LL * (f1 / l) * (f2 / l) * (sum[r] - sum[l - 1]);
}
printf("%lld
", ans);
}
return 0;
}