# [BZOJ3994][SDOI2015]约数个数和

## 3994: [SDOI2015]约数个数和

Time Limit: 20 Sec  Memory Limit: 128 MB Submit: 1104  Solved: 762 [Submit][Status][Discuss]

## Description

设d(x)为x的约数个数，给定N、M，求

## Output

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

2
7 4
5 6

110
121

## HINT

1<=N, M<=50000

1<=T<=50000

$ans=\sum_{x=1}^n\sum_{y=1}^m\sum_{i\mid x}\sum_{j\mid y}\left[gcd\left(i,j\right)=1\right]$
$=\sum_{i=1}^n\sum_{j=1}^m\lfloor\frac{n}{i}\rfloor\lfloor\frac{m}{j}\rfloor\left[gcd\left(i,j\right)=1\right]$
$=\sum_{i=1}^n\sum_{j=1}^m\lfloor\frac{n}{i}\rfloor\lfloor\frac{m}{j}\rfloor\sum_{d\mid i,d\mid j}\mu\left(d\right)$
$=\sum_{d=1}^n\mu\left(d\right)\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{d}\rfloor}\lfloor\frac{n}{id}\rfloor\lfloor\frac{m}{id}\rfloor$
$=\sum_{d=1}^n\mu\left(d\right)\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{d}\rfloor}\lfloor\frac{\lfloor\frac{n}{d}\rfloor}{i}\rfloor\lfloor\frac{\lfloor\frac{m}{d}\rfloor}{i}\rfloor$
$=\sum_{d=1}^n\mu\left(d\right)\left(\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\lfloor\frac{\lfloor\frac{n}{d}\rfloor}{i}\rfloor\right)\left(\sum_{j=1}^{\lfloor\frac{m}{d}\rfloor}\lfloor\frac{\lfloor\frac{m}{d}\rfloor}{i}\rfloor\right)$

#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 50000 + 10;
bool mark[maxn] = {false};
int mu[maxn], g[maxn] = {0}, sum[maxn];
int pri[maxn], prn = 0;
void shai(){
mu[1] = 1;
for(int i = 2; i < maxn; i++){
if(!mark[i]){
mu[i] = -1;
pri[++prn] = i;
}
for(int j = 1; j <= prn && pri[j] * i < maxn; j++){
mark[i * pri[j]] = true;
if(i % pri[j] == 0){
mu[i * pri[j]] = 0;
break;
}
else mu[i * pri[j]] = -mu[i];
}
}
for(int i = 1; i < maxn; i++)
for(int j = i; j < maxn; j += i)
g[j]++;
sum[0] = g[0] = 0;
for(int i = 1; i < maxn; i++){
sum[i] = mu[i] + sum[i - 1];
g[i] += g[i - 1];
}
}
int main(){
shai();
int T, n, m;
ll ans;
scanf("%d", &T);
while(T--){
scanf("%d %d", &n, &m);
if(n > m) swap(n, m);
ans = 0;
for(int p, i = 1; i <= n; i = p + 1){
p = min(n / (n / i), m / (m / i));
ans += (ll) (sum[p] - sum[i - 1]) * g[n / p] * g[m / p];
}
printf("%lld\n", ans);
}
return 0;
}

posted @ 2017-10-16 21:35  Elder_Giang  阅读(143)  评论(0编辑  收藏  举报