[bzoj3994][SDOI2015]约数个数和-数论
2017-03-21 16:06
344 查看
Brief Description
计算\(\sum_{i\leqslant n}\sum_{j\leqslant m}\sigma_0(ij)\).
Algorithm Design
首先证明一个结论
\[d(ij) = \sum_{i\leqslant n}\sum_{j \leqslant m}[(i,j)=1]\]
我们不显式地证明它, 仅仅直观地考虑每个质数对于答案的贡献就好.
有了这个结论我们开始推式子:
\[
\begin{aligned}
\sum_{i\leqslant n}\sum_{j\leqslant m}\sigma_0(ij) & = \sum_{i\leqslant n}\sum_{j\leqslant m} \sum_{a|i} \sum_{b|j} [(i,j)=1]\\ & =\sum_{i\leqslant n}\sum_{j\leqslant m}\sum_{a|i}\sum_{b|j}\sum_{x|(i,j)}\mu(x)\\& =\sum_{i\leqslant n}\sum_{j \leqslant m}\sum_{x|i+j}\mu(x)\sigma_0(\frac ix)\sigma_0(\frac jx) \\ &=\sum_{x \leqslant n} \mu(x)\sum_{i \leqslant \lfloor \frac nx \rfloor} \sigma_0(i)\sum_{j \leqslant \lfloor \frac mx \rfloor}\sigma_0(j)
\end{aligned}
\]
有了最后的式子, 我们就可以开始乱搞了.
复杂度\(O(n+T\sqrt n)\)
Code
#include <algorithm> #include <cctype> #include <cstdio> #define ll long long const int maxn = 50000 + 10; int prime[maxn], tot; int mu[maxn], sigma[maxn], summu[maxn]; ll sumsigma[maxn]; bool check[maxn]; int read() { int x = 0, f = 1; char ch = getchar(); while (!isdigit(ch)) { if (ch == '-') f = -1; ch = getchar(); } while (isdigit(ch)) { x = x * 10 + ch - '0'; ch = getchar(); } return x * f; } void shake() { int minPrimeCnt[maxn]; mu[1] = 1, sigma[1] = 1; for (int i = 2; i < maxn; i++) { if (!check[i]) { prime[tot++] = i; mu[i] = -1; sigma[i] = 2; minPrimeCnt[i] = 1; } for (int j = 0; j < tot; j++) { int x = i * prime[j]; if (x >= maxn) break; check[x] = 1; if (i % prime[j] == 0) { mu[x] = 0; minPrimeCnt[x] = minPrimeCnt[i] + 1; sigma[x] = sigma[i] / (minPrimeCnt[i] + 1) * (minPrimeCnt[x] + 1); break; } else { mu[x] = -mu[i]; sigma[x] = sigma[i] << 1; minPrimeCnt[x] = 1; } } } summu[0] = 0; for (int i = 1; i < maxn; i++) summu[i] = summu[i - 1] + mu[i]; for (int i = 1; i < maxn; i++) sumsigma[i] = sumsigma[i - 1] + sigma[i]; } ll F(int n, int m) { if (n > m) std::swap(n, m); ll ans = 0; for (int i = 1, last = 1; i <= n; i = last + 1) { last = std::min(n / (n / i), m / (m / i)); ans += (summu[last] - summu[i - 1]) * sumsigma[n / i] * sumsigma[m / i]; } return ans; } int main() { #ifndef ONLINE_JUDGE freopen("input", "r", stdin); #endif shake(); int kase = read(); while (kase--) { int n = read(), m = read(); printf("%lld\n", F(n, m)); } return 0; }
相关文章推荐
- 【bzoj3994】【SDOI2015】约数个数和【数论】【反演】
- [BZOJ]3994 [SDOI2015]约数个数和 莫比乌斯 + 分块
- BZOJ 3994: [SDOI2015]约数个数和|莫比乌斯反演
- BZOJ3994:[SDOI2015]约数个数和——题解
- BZOJ 3994: [SDOI2015]约数个数和 [莫比乌斯反演 转化]
- 【bzoj3994】[SDOI2015]约数个数和 线性筛法+莫比乌斯反演+数论分块
- BZOJ_3994_[SDOI2015]约数个数和_莫比乌斯反演
- BZOJ 3994 [SDOI2015]约数个数和 (莫比乌斯反演)
- bzoj 3994: [SDOI2015]约数个数和 莫比乌斯反演
- 【bzoj3994】[SDOI2015]约数个数和 莫比乌斯反演
- BZOJ 3994 [SDOI2015]约数个数和 莫比乌斯反演
- [BZOJ3994][SDOI2015]约数个数和(数论)
- [SDOI2015][bzoj3994] 约数个数和 [莫比乌斯反演]
- bzoj3994: [SDOI2015]约数个数和 莫比乌斯反演
- BZOJ 3994 Sdoi2015 约数个数和 莫比乌斯反演
- BZOJ 3994: [SDOI2015]约数个数和 莫比乌斯反演
- BZOJ 3994 [SDOI2015]约数个数和 (神定理+莫比乌斯反演)
- 【BZOJ3994】[SDOI2015]约数个数和 莫比乌斯反演
- bzoj3994 [SDOI2015]约数个数和
- bzoj 3994 [SDOI2015]约数个数和