[关闭]
@11101001 2018-06-14T17:50:01.000000Z 字数 2092 阅读 709

bzoj3529: [Sdoi2014]数表

莫比乌斯反演


题目链接

bzoj3529: [Sdoi2014]数表

题解

表示的约束和
就是求这个


首先,我们不考虑a

那么
则答案就是



对于我们可以nlogn筛出来
考虑a的限制,我们可以离线做
对于这部分
对于询问a的排序,对于排序,对于每次询问,把的每个按上式丢到一个bit里维护一下前缀和
复杂度

代码

  1. #include <queue>
  2. #include <cstdio>
  3. #include <algorithm>
  4. inline int read() {
  5. int x = 0;
  6. char c = getchar();
  7. while(c < '0' || c > '9')c = getchar();
  8. while(c <= '9' && c >= '0')x = x * 10 + c - '0',c = getchar();
  9. return x;
  10. }
  11. const int mod = (1 << 31);
  12. const int maxn = 100007;
  13. int p[maxn],mu[maxn],mx; bool vis[maxn];
  14. struct node {
  15. int n,m,a,id;
  16. bool operator < (const node & k)const {
  17. return a < k.a;
  18. }
  19. } q[maxn];
  20. std::pair<int,int>F[maxn];
  21. void getmu() {
  22. int size = mx,num = 0;
  23. mu[1] = 1;
  24. for(int i = 2;i <= size;++ i) {
  25. if(!vis[i]) p[++ num] = i,mu[i] = -1;
  26. for(int j = 1;j <= num && i * p[j] <= size;++ j) {
  27. vis[i * p[j]] = true;
  28. if(i % p[j] == 0) {
  29. mu[i * p[j]] = 0; break;
  30. } mu[i * p[j]] = -mu[i];
  31. }
  32. }
  33. for(int i = 1;i <= size;++ i)
  34. for(int j = i;j <= size;j += i)
  35. F[j].first += i;
  36. for(int i = 1;i <= size;++ i)F[i].second = i;
  37. }
  38. int ans[maxn];
  39. #define lowbit(x) x&(-x)
  40. int bit[maxn << 1];
  41. void add(int x,int num) {
  42. for(int i = x;i <= mx; i += lowbit(i))bit[i] += num;
  43. }
  44. int query(int x) {
  45. int ret = 0;
  46. for(int i = x;i; i -= lowbit(i)) ret += bit[i];
  47. return ret;
  48. }
  49. void solve(int x) {
  50. int n = q[x].n,m = q[x].m;
  51. for(int i = 1,j;i <= q[x].n;i = j + 1) {
  52. j = std::min(m / (m / i),n / (n/i));
  53. ans[q[x].id] += (n / i) * (m / i) * (query(j) - query(i - 1));
  54. }
  55. }
  56. int main() {
  57. int k = read();
  58. for(int i = 1;i <= k;++ i) {
  59. q[i].n = read(),q[i].m = read(),q[i].a = read();
  60. if(q[i].n > q[i].m) std::swap(q[i].n,q[i].m);
  61. q[i].id = i; mx = std::max(mx,q[i].n);
  62. }
  63. getmu();
  64. std::sort(q + 1,q + k + 1);
  65. std::sort(F + 1,F + mx + 1);
  66. for(int i = 1,now = 0;i <= k;++ i) {
  67. for(;now + 1 <= mx && F[now + 1].first <= q[i].a;) {
  68. now ++;
  69. for(int j = F[now].second;j <= mx;j += F[now].second) {
  70. //printf("%d\n",now);
  71. add(j,F[now].first * mu[j / F[now].second]);
  72. }
  73. }
  74. solve(i);
  75. }
  76. //printf("%d\n",mod);
  77. for(int i = 1;i <= k;++ i) {
  78. printf("%d\n",ans[i] & 0x7fffffff );
  79. }
  80. return 0;
  81. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注