经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C++ » 查看文章
BZOJ3529: [Sdoi2014]数表(莫比乌斯反演 树状数组)
来源:cnblogs  作者:自为风月马前卒  时间:2018/12/11 9:29:39  对本文有异议

题意

题目链接

Sol

首先不考虑\(a\)的限制

我们要求的是

\[\sum_{i = 1}^n \sum_{j = 1}^m \sigma(gcd(i, j))\]

用常规的套路可以化到这个形式

\[\sum_{d = 1}^n \sigma (d) \sum_{k = 1}^{\frac{n}{d}} \mu(k) \frac{n}{kd} \frac{m}{kd}\]

\(kd = T\)

那么

\(\sum_{T = 1}^n \left\lfloor \frac{n}{T} \right\rfloor \left\lfloor \frac{m}{T} \right\rfloor \sum_{d \ | T} \sigma(d) \mu(\frac{T}{d})\)

然后按照套路筛出后面的卷积。

但是现在有\(a\)的限制了。。

那么可以直接离线之后树状数组维护一下。

时间复杂度:\(O(T\sqrt{n}logn)\)

约数个数和用埃氏筛两行就筛出来了

  1. #include<bits/stdc++.h>
  2. #define chmax(a, b) (a = (a > b ? a : b))
  3. #define chmin(a, b) (a = (a < b ? a : b))
  4. //#define int long long
  5. using namespace std;
  6. const int MAXN = 3e5 + 10;
  7. inline int read() {
  8. char c = getchar(); int x = 0, f = 1;
  9. while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
  10. while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
  11. return x * f;
  12. }
  13. int T, mx, mu[MAXN], phi[MAXN], prime[MAXN], tot, vis[MAXN], si[MAXN], out[MAXN], p[MAXN];
  14. struct Query{
  15. int N, M, a, id;
  16. bool operator < (const Query &rhs) const {
  17. return a < rhs.a;
  18. }
  19. }q[MAXN];
  20. int comp(const Query &a, const Query &b) {
  21. return a.id < b.id;
  22. }
  23. int comp2(const int &a, const int &b) {
  24. return si[a] < si[b];
  25. }
  26. void Get(int N) {
  27. for(int i = 1; i <= N; i++)
  28. for(int j = i; j <= N; j += i) si[j] += i;
  29. vis[1] = 1; mu[1] = 1;
  30. for(int i = 2; i <= N; i++) {
  31. if(!vis[i]) prime[++tot] = i, mu[i] = -1;
  32. for(int j = 1; j <= tot && i * prime[j] <= N; j++) {
  33. vis[i * prime[j]] = 1;
  34. if(!(i % prime[j])) {mu[i * prime[j]] = 0; break;}
  35. else mu[i * prime[j]] = -mu[i];
  36. }
  37. }
  38. }
  39. #define lb(x) (x & (-x))
  40. int Tr[MAXN];
  41. void Add(int x, int val) {
  42. while(x <= mx) Tr[x] += val, x += lb(x);
  43. }
  44. int Sum(int x) {
  45. int ans = 0;
  46. while(x) ans += Tr[x], x -= lb(x);
  47. return ans;
  48. }
  49. int solve(int n, int m) {
  50. int rt = 0, las = 0, now;
  51. for(int i = 1, nxt; i <= n; i = nxt + 1) {
  52. nxt = min(m / (m / i), n / (n / i));
  53. now = Sum(nxt);
  54. rt += (n / i) * (m / i) * (now - las);
  55. las = now;
  56. }
  57. return rt;
  58. }
  59. signed main() {
  60. T = read();
  61. for(int i = 1; i <= T; i++) {
  62. q[i].N = read(), q[i].M = read(), q[i].a = read(), q[i].id = i;
  63. if(q[i].N > q[i].M) swap(q[i].N, q[i].M);;
  64. chmax(mx, q[i].N);
  65. }
  66. Get(mx);
  67. for(int i = 1; i <= mx; i++) p[i] = i;
  68. sort(p + 1, p + mx + 1, comp2);
  69. sort(q + 1, q + T + 1);
  70. for(int t = 1, d = 1; t <= T; t++) {
  71. for(; d <= mx && si[p[d]] <= q[t].a; d++) {
  72. for(int k = p[d]; k <= mx; k += p[d]) {
  73. if(!mu[k / p[d]]) continue;
  74. Add(k, si[p[d]] * mu[k / p[d]]);
  75. }
  76. }
  77. out[q[t].id] = solve(q[t].N, q[t].M);
  78. }
  79. for(int i = 1; i <= T; i++)
  80. printf("%d\n", out[i] < 0 ? out[i] + 2147483648 : out[i]);
  81. //printf("%d\n", out[i] <);
  82. return 0;
  83. }
 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号