[关闭]
@qq290637843 2020-11-24T01:26:41.000000Z 字数 5401 阅读 232

2020杭电第六场第八题题解

表示的最大质因数,表示的最小质因数,表示小于等于的最大质数,表示小于的最大质数,表示大于的最小质数。

注意


故实际要对所有求出


倒过来就是

于是可以将从大到小递推求值,起始条件如下:

于是任务变为对所有形如,以及求出

而(下文中

对于(上式中最后一个等号仅对此情况成立)递推即可,而时,上式中所以不再变化。

  1. #include <bits/stdc++.h>
  2. namespace fast_pool {
  3. constexpr size_t const size = 481 << 20;
  4. unsigned char data[size];
  5. unsigned char* ptr = data;
  6. void clear() {ptr = data;}
  7. void* fast_alloc(size_t n) {ptr += n; return ptr - n;}
  8. };
  9. template<class T>
  10. class myallocator {
  11. public:
  12. typedef T value_type;
  13. typedef value_type* pointer;
  14. typedef value_type& reference;
  15. typedef value_type const* const_pointer;
  16. typedef value_type const& const_reference;
  17. typedef size_t size_type;
  18. typedef ptrdiff_t difference_type;
  19. pointer allocate(size_t n, const T* pHint = 0) {
  20. return (pointer)(fast_pool::fast_alloc(n * sizeof(T)));
  21. }
  22. void deallocate(pointer p, size_type n) {}
  23. void destroy(T* p) {p->~T();}
  24. void construct(T* p, const T& val) {::new((void *)p) T(val);}
  25. size_t max_size() const throw() {
  26. return (fast_pool::size + fast_pool::data - fast_pool::ptr) / sizeof(T);
  27. }
  28. T* address(T& val) const {return &val;}
  29. const T* address(const T& val) const {return &val;}
  30. myallocator() throw() {}
  31. myallocator(const T* p) throw() {}
  32. ~myallocator() throw() {}
  33. template <typename _other> struct rebind { typedef myallocator<_other> other; };
  34. };
  35. std::stringstream iss;
  36. std::stringstream oss;
  37. std::string instr;
  38. using ul = std::uint32_t;
  39. using li = std::int32_t;
  40. using ull = std::uint64_t;
  41. using ll = std::int64_t;
  42. const ul maxn = 1e9;
  43. const ul maxsqrtn = 31622;
  44. const ul maxd = maxsqrtn;
  45. ul T;
  46. ul n, k;
  47. ul nid1[maxsqrtn + 1];
  48. ul nid2[maxsqrtn + 1];
  49. ul nv[maxsqrtn + maxsqrtn + 1];
  50. ul sqrtnv[maxsqrtn + maxsqrtn + 1];
  51. std::vector<ul, myallocator<ul>> ans2[maxsqrtn + maxsqrtn + 1];
  52. ul nc;
  53. void initid(ul n, ul id1[], ul id2[], ul v[], ul& c)
  54. {
  55. for (ul l = 1, r, i = 1; l <= n; l = r + 1, ++i) {
  56. ul nq = n / l;
  57. r = n / nq;
  58. if (nq <= r) {
  59. id2[nq] = i;
  60. }
  61. if (r <= nq) {
  62. id1[r] = i;
  63. }
  64. v[i] = r;
  65. c = i;
  66. }
  67. }
  68. ul getid(ul x, ul n, const ul id1[], const ul id2[])
  69. {
  70. return ull(x) * x <= n ? id1[x] : id2[n / x];
  71. }
  72. std::vector<ul, myallocator<ul>> prime(maxd);
  73. std::vector<ul, myallocator<ul>> fprime(maxd);
  74. std::vector<bool> notprime(maxd + 1);
  75. ul alcntprime[maxsqrtn + 1];
  76. ul ncntprime[maxsqrtn + maxsqrtn + 1];
  77. ul kp;
  78. void initcntprime(ul n, const ul id1[], const ul id2[], const ul v[], ul c, ul cntprime[])
  79. {
  80. for (ul i = 1; i <= c; ++i) {
  81. cntprime[i] = v[i] - 1;
  82. }
  83. for (ul gk : prime) {
  84. if (gk * gk > n) {
  85. break;
  86. }
  87. for (ul i = c; i >= 2 && v[i] >= gk * gk; --i) {
  88. cntprime[i] -= cntprime[getid(v[i] / gk, n, id1, id2)];
  89. cntprime[i] += alcntprime[gk - 1];
  90. }
  91. }
  92. }
  93. ul finalans2[maxsqrtn + maxsqrtn + 1];
  94. void initans2()
  95. {
  96. for (ul i = 1; i <= nc; ++i) {
  97. ans2[i][alcntprime[sqrtnv[i]]] = 1 - ncntprime[i] + alcntprime[sqrtnv[i]];
  98. for (ul j = alcntprime[sqrtnv[i]]; j >= 1 && j >= kp + 1; --j) {
  99. ul ii = getid(nv[i] / fprime[j], n, nid1, nid2);
  100. if (j <= alcntprime[sqrtnv[ii]]) {
  101. ans2[i][j - 1] = ans2[i][j] - ans2[ii][j];
  102. } else if (j <= ncntprime[ii]) {
  103. ans2[i][j - 1] = ans2[i][j] - (j - ncntprime[ii] + 1);
  104. } else {
  105. ans2[i][j - 1] = ans2[i][j] - 1;
  106. }
  107. }
  108. if (kp <= alcntprime[sqrtnv[i]]) {
  109. finalans2[i] = ans2[i][kp];
  110. } else if (kp <= ncntprime[i]) {
  111. finalans2[i] = kp - ncntprime[i] + 1;
  112. } else {
  113. finalans2[i] = 1;
  114. }
  115. }
  116. }
  117. int main()
  118. {
  119. std::ios::sync_with_stdio(false);
  120. std::cin.tie(0);
  121. iss.tie(0);
  122. oss.tie(0);
  123. std::getline(std::cin, instr, char(0));
  124. iss.str(instr);
  125. fprime.resize(0);
  126. fprime.push_back(1);
  127. prime.resize(0);
  128. for (ul i = 2; i <= maxd; ++i) {
  129. alcntprime[i] = alcntprime[i - 1];
  130. if (!notprime[i]) {
  131. fprime.push_back(i);
  132. prime.push_back(i);
  133. ++alcntprime[i];
  134. }
  135. for (ul p : prime) {
  136. if (p * i > maxd) {
  137. break;
  138. }
  139. notprime[p * i] = true;
  140. if (i % p == 0) {
  141. break;
  142. }
  143. }
  144. }
  145. iss >> T;
  146. for (ul Case = 1; Case <= T; ++Case) {
  147. iss >> n >> k;
  148. initid(k, nid1, nid2, nv, nc);
  149. initcntprime(k, nid1, nid2, nv, nc, ncntprime);
  150. kp = ncntprime[nc];
  151. initid(n, nid1, nid2, nv, nc);
  152. initcntprime(n, nid1, nid2, nv, nc, ncntprime);
  153. for (ul i = 1; i <= nc; ++i) {
  154. sqrtnv[i] = std::sqrt(nv[i]);
  155. while ((sqrtnv[i] + 1) * (sqrtnv[i] + 1) <= nv[i]) {
  156. ++sqrtnv[i];
  157. }
  158. ans2[i].resize(alcntprime[sqrtnv[i]] + 1);
  159. }
  160. initans2();
  161. ul ans = 0;
  162. for (ul i = 1; i <= nc; ++i) {
  163. ans += nv[nc + 1 - i] * finalans2[i];
  164. if (i != 1) {
  165. ans -= nv[nc + 1 - i] * finalans2[i - 1];
  166. }
  167. }
  168. oss << ans << '\n';
  169. }
  170. std::cout << oss.str();
  171. return 0;
  172. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注