二次联通门 : BZOJ 3994: [SDOI2015]约数个数和
$LARGE Answer =sum_{i=1}^{n}sum_{j=1}^{m}d(ij)$
$LARGE = sum_{i=1}^{n}sum_{j=1}^{m}sum_{a|i}sum_{b|j}[gcd(a,b)=1]$
$LARGE = sum_{i=1}^{n}sum_{j=1}^{m}lfloor dfrac{n}{i} floor lfloor dfrac{m}{j} floor [gcd(a,b)=1]$
$LARGE = sum_{i=1}^{n}sum_{j=1}^{m}lfloor dfrac{n}{i} floor lfloor dfrac{m}{j} floor sum_{d|gcd(i,j)}mu(d)$
$LARGE = sum_{d=1}^nmu(d)sum_{i=1}^{n/d}sum_{j=1}^{m/d}lfloor dfrac {n}{id} floor lfloor dfrac {m} {jd} floor$
$LARGE = sum_{d=1}^nmu(d)sum_{i=1}^{n/d}sum_{j=1}^{m/d}lfloor dfrac {dfrac {n}{d}}{i} floor lfloor dfrac {dfrac {m}{d}} {j} floor$
设 $LARGE f(n)=sum_{i=1}^{n} lfloor dfrac {n}{i} floor$
代回原式得:
$LARGE Answer =sum_{d=1}^nmu(d)f(dfrac nd) f(dfrac md)$
/* BZOJ 3994: [SDOI2015]约数个数和 莫比乌斯反演 */ #include <cstdio> #include <iostream> #define rg register inline void read (int &n) { rg char c = getchar (); for (n = 0; !isdigit (c); c = getchar ()); for (; isdigit (c); n = n * 10 + c - '0', c = getchar ()); } #define Max 50008 int mu[Max], p[Max], sm[Max], f[Max]; bool is[Max]; void Euler (int N) { int C = 0; rg int i, j, k; mu[1] = 1; for (i = 2; i <= N; ++ i) { if (!is[i]) p[++ C] = i, mu[i] = -1; for (j = 1; j <= C; ++ j) { k = i * p[j]; if (k > N) break; is[k] = true; if (i % p[j] == 0) { mu[k] = 0; break; } else mu[k] = -mu[i]; } } for (i = 1; i <= N; ++ i) sm[i] = sm[i - 1] + mu[i]; } inline int min (int a, int b) { return a < b ? a : b; } int F (int N) { int res = 0; for (rg int i = 1, j; i <= N; i = j + 1) j = N / (N / i), res += (N / i) * (j - i + 1); return res; } typedef long long LL; #ifdef WIN32 #define PLL "%I64d" #else #define PLL "%lld" #endif int main (int argc, char *argv[]) { int T, N, M; read (T); rg int i, j; Euler (Max - 1); for (i = 1; i < Max; ++ i) f[i] = F (i); for (LL Answer; T; -- T) { read (N), read (M); Answer = 0; if (N > M) std :: swap (N, M); for (i = 1; i <= N; i = j + 1) { j = min (N / (N / i), M / (M / i)); Answer += (LL) (sm[j] - sm[i - 1]) * f[N / i] * f[M / i]; } printf (PLL" ", Answer); } return 0; }