a n s = ∑ i = 1 N ∑ j = 1 M d ( i j ) \begin{aligned} ans= \sum_{i=1}^{N}\sum_{j=1}^{M}d(ij) \end{aligned} ans=i=1∑Nj=1∑Md(ij)
现在有个式子:
d ( i j ) = ∑ x ∣ i ∑ y ∣ j [ gcd ( x , y ) = = 1 ] \begin{aligned} d(ij)= \sum_{x \mid i}\sum_{y \mid j}[\gcd(x,y)==1] \end{aligned} d(ij)=x∣i∑y∣j∑[gcd(x,y)==1]
所以:
a n s = ∑ i = 1 N ∑ j = 1 M ∑ x ∣ i ∑ y ∣ j [ gcd ( x , y ) = = 1 ] \begin{aligned} ans= \sum_{i=1}^{N}\sum_{j=1}^{M}\sum_{x \mid i}\sum_{y \mid j}[\gcd(x,y)==1] \end{aligned} ans=i=1∑Nj=1∑Mx∣i∑y∣j∑[gcd(x,y)==1]
给 [ gcd ( x , y ) = = 1 ] [\gcd(x,y)==1] [gcd(x,y)==1]替换掉:
a n s = ∑ d = 1 min ( N , M ) μ ( d ) ∑ i = 1 N ∑ j = 1 M ∑ x ∣ i ∑ y ∣ j [ d ∣ gcd ( x , y ) ] \begin{aligned} ans= \sum_{d=1}^{\min(N,M)}\mu(d)\sum_{i=1}^{N}\sum_{j=1}^{M}\sum_{x \mid i}\sum_{y \mid j}[d \mid \gcd(x,y)] \end{aligned} ans=d=1∑min(N,M)μ(d)i=1∑Nj=1∑Mx∣i∑y∣j∑[d∣gcd(x,y)]
我们枚举 x x x, y y y:
a n s = ∑ d = 1 min ( N , M ) μ ( d ) ∑ x = 1 N ∑ y = 1 M [ d ∣ gcd ( x , y ) ] ⌊ N x ⌋ ⌊ M y ⌋ \begin{aligned} ans= \sum_{d=1}^{\min(N,M)}\mu(d)\sum_{x=1}^{N}\sum_{y=1}^{M}[d \mid \gcd(x,y)]\lfloor\frac{N}{x}\rfloor\lfloor\frac{M}{y}\rfloor \end{aligned} ans=d=1∑min(N,M)μ(d)x=1∑Ny=1∑M[d∣gcd(x,y)]⌊xN⌋⌊yM⌋
a n s = ∑ d = 1 min ( N , M ) μ ( d ) ∑ x = 1 ⌊ N d ⌋ ∑ y = 1 ⌊ M d ⌋ ⌊ N x d ⌋ ⌊ M y d ⌋ \begin{aligned} ans= \sum_{d=1}^{\min(N,M)}\mu(d)\sum_{x=1}^{\lfloor\frac{N}{d}\rfloor}\sum_{y=1}^{\lfloor\frac{M}{d}\rfloor}\lfloor\frac{N}{xd}\rfloor\lfloor\frac{M}{yd}\rfloor \end{aligned} ans=d=1∑min(N,M)μ(d)x=1∑⌊dN⌋y=1∑⌊dM⌋⌊xdN⌋⌊ydM⌋
a n s = ∑ d = 1 min ( N , M ) μ ( d ) ∑ x = 1 ⌊ N d ⌋ ⌊ N x d ⌋ ∑ y = 1 ⌊ M d ⌋ ⌊ M y d ⌋ \begin{aligned} ans= \sum_{d=1}^{\min(N,M)}\mu(d)\sum_{x=1}^{\lfloor\frac{N}{d}\rfloor}\lfloor\frac{N}{xd}\rfloor\sum_{y=1}^{\lfloor\frac{M}{d}\rfloor}\lfloor\frac{M}{yd}\rfloor \end{aligned} ans=d=1∑min(N,M)μ(d)x=1∑⌊dN⌋⌊xdN⌋y=1∑⌊dM⌋⌊ydM⌋
我们令 f ( i ) = ∑ i = 1 n ⌊ n i ⌋ f(i)=\sum_{i=1}^{n}\lfloor\frac{n}{i}\rfloor f(i)=∑i=1n⌊in⌋
a n s = ∑ d = 1 min ( N , M ) μ ( d ) f ( ⌊ N i ⌋ ) f ( ⌊ M i ⌋ ) \begin{aligned} ans= \sum_{d=1}^{\min(N,M)}\mu(d)f(\lfloor\frac{N}{i}\rfloor)f(\lfloor\frac{M}{i}\rfloor) \end{aligned} ans=d=1∑min(N,M)μ(d)f(⌊iN⌋)f(⌊iM⌋)
f ( n ) f(n) f(n)就是约数个数函数的前缀和,我们预处理可以 O ( 1 ) O(1) O(1)查询,然后分块求 a n s ans ans
#include
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
template <typename T>
void out(T x) { cout << x << endl; }
ll fast_pow(ll a, ll b, ll p) {ll c = 1; while(b) { if(b & 1) c = c * a % p; a = a * a % p; b >>= 1;} return c;}
ll exgcd(ll a, ll b, ll &x, ll &y) { if(!b) {x = 1; y = 0; return a; } ll gcd = exgcd(b, a % b, y, x); y-= a / b * x; return gcd; }
const int N = 5e4 + 100;
int sum[N], d[N], mu[N], prime[N], tot;
//d[i]表示i的约数个数
//sum[i]表示i的最小质因子的最高次幂(线性筛用的是最小质因子去筛的)
bool mark[N];
void get_d_mu()
{
mark[1] = mark[0] = true;
tot = 0;
mu[1] = d[1] = sum[1] = 1;
for(int i = 2; i < N; i ++)
{
if(!mark[i])
{
prime[tot ++] = i;
mu[i] = -1;
d[i] = 2;
sum[i] = 1;
}
for(int j = 0; j < tot && i * prime[j] < N; j ++)
{
mark[i * prime[j]] = true;
if(i % prime[j] == 0)
{
d[i * prime[j]] = d[i] / (sum[i] + 1) * (sum[i] + 2);
sum[i * prime[j]] = sum[i] + 1;
mu[i * prime[j]] = 0;
break;
}
mu[i * prime[j]] = -mu[i];
d[i * prime[j]] = 2 * d[i];
sum[i * prime[j]] = 1;
}
}
for(int i = 1; i < N; i ++)
{
mu[i] += mu[i - 1];
d[i] += d[i - 1];
}
}
ll cal(ll n, ll m)
{
if(n > m)
swap(n, m);
ll ans = 0;
for(ll i = 1, j = 1; i <= n; i = j + 1)
{
j = min(n / (n / i), m / (m / i));
ans += 1ll * (mu[j] - mu[i - 1]) * d[n / i] * d[m / i];
}
return ans;
}
int main()
{
ios::sync_with_stdio(false);
get_d_mu();
int t;
cin >> t;
while(t --)
{
ll n, m;
cin >> n >> m;
cout << cal(n, m) << endl;
}
}