[关闭]
@wsndy-xx 2018-06-14T15:02:20.000000Z 字数 1243 阅读 828

Luogu 1447 能量采集

题解


question

slove

不妨设
原式



then

then


反演得

考虑每个
时的取值为 ,因为 的最大值为


对两部分分别整除分块


Code

  1. #include <bits/stdc++.h>
  2. const int N = 1e5 + 10;
  3. #define LL long long
  4. LL prime[N], mu[N], bo[N];
  5. LL n, m;
  6. void Get_mu() {
  7. mu[1] = 1;
  8. for(int i = 2; i <= N - 10; i ++) {
  9. if(!bo[i]) {prime[++ prime[0]] = i; mu[i] = -1;}
  10. for(int j = 1; j <= prime[0] && prime[j] * i <= N - 10; j ++) {
  11. bo[prime[j] * i] = 1;
  12. if(i % prime[j] == 0) {
  13. mu[i * prime[j]] = 0;
  14. break;
  15. } else mu[i * prime[j]] = - mu[i];
  16. }
  17. }
  18. for(int i = 2; i <= N - 10; i ++) mu[i] += mu[i - 1];
  19. }
  20. LL Calc(LL n_, LL m_) {
  21. LL ret = 0;
  22. for(int i = 1, r; i <= n_; i = r + 1) {
  23. r = std:: min(n_ / (n_ / i), m_ / (m_ / i));
  24. ret += 1LL * (mu[r] - mu[i - 1]) * (n_ / i) * (m_ / i);
  25. }
  26. return ret;
  27. }
  28. int main() {
  29. Get_mu();
  30. std:: cin >> n >> m;
  31. if(n > m) std:: swap(n, m);
  32. LL Ans = 0;
  33. for(int i = 1, r; i <= n; i = r + 1) {
  34. r = std:: min(n / (n / i), m / (m / i));
  35. Ans += 1LL * (i + r) * (r - i + 1) / 2 * Calc(n / i, m / i);
  36. }
  37. std:: cout << 2 * Ans - n * m;
  38. return 0;
  39. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注