Description

$d(x)$$x$的约数个数，给定$N,M$，求$$\sum_{i=1}{N}\sum_{j=1}{M}d(ij)$$。

Output

$T$行，每行一个整数，表示你所求的答案。

2
7 4
5 6

110
121

HINT

$1 \le N, M \le 50000$
$1 \le T \le 50000$

$\sum_{i=1}^{N}\sum_{j=1}^{M}\lfloor\frac{N}{i}\rfloor\lfloor\frac{M}{j}\rfloor\lbrack gcd(i,j)=1 \rbrack$

#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;

typedef long long ll;
#define maxn (50010)
int f[maxn],mu[maxn],prime[maxn],n,m,tot; bool exist[maxn];

inline int calc(int x)
{
int ret = 0;
for (int i = 1,last;i <= x;i = last+1)
{
last = min(x,x/(x/i));
ret += (x/i)*(last-i+1);
}
return ret;
}
{
mu[1] = 1;
for (int i = 2;i <= 50000;++i)
{
if (!exist[i]) { prime[++tot] = i; mu[i] = -1; }
for (int j = 1;j <= tot&&prime[j]*i <= 50000;++j)
{
exist[i*prime[j]] = true;
if (i % prime[j] == 0) { mu[i*prime[j]] = 0; break; }
mu[i*prime[j]] = -mu[i];
}
}
for (int i = 1;i <= 50000;++i) mu[i] += mu[i-1],f[i] = calc(i);
}

inline ll work()
{
if (n > m) swap(n,m);
ll ret = 0;
for (int i = 1,last;i <= n;i = last+1)
{
last = min(n,min(n/(n/i),m/(m/i)));
ret += (ll)(mu[last]-mu[i-1])*((ll)f[n/i]*f[m/i]);
}
return ret;
}

int main()
{
freopen("3994.in","r",stdin);
freopen("3994.out","w",stdout);