1
0

primes.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. #include <vector>
  2. #include <string>
  3. #include <queue>
  4. #include <iostream>
  5. #include <algorithm>
  6. #include <unordered_map>
  7. typedef long long LL;
  8. struct Node{
  9. std::unordered_map<int, Node*> children;
  10. bool terminal;
  11. Node(){
  12. terminal = false;
  13. }
  14. };
  15. struct Sieve{
  16. LL limit;
  17. std::vector<bool> prime;
  18. Sieve(LL limit){
  19. this->limit = limit;
  20. prime = std::vector<bool>(limit + 1, false);
  21. }
  22. std::vector<LL> to_list(){
  23. std::vector<LL> result;
  24. result.push_back(2);
  25. result.push_back(3);
  26. for(LL p = 5; p <= limit; p++){
  27. if(prime[p]){
  28. result.push_back(p);
  29. }
  30. }
  31. return result;
  32. }
  33. void omit_squares(){
  34. LL r = 5;
  35. while(r * r < limit){
  36. if(prime[r]){
  37. LL i = r * r;
  38. while(i < limit){
  39. prime[i] = false;
  40. i = i + r * r;
  41. }
  42. }
  43. r += 1;
  44. }
  45. }
  46. void step1(LL x, LL y){
  47. LL n = (4 * x * x) + (y * y);
  48. if(n <= limit && (n % 12 == 1 || n % 12 == 5)){
  49. prime[n] = !prime[n];
  50. }
  51. }
  52. void step2(LL x, LL y){
  53. LL n = (3 * x * x) + (y * y);
  54. if(n <= limit && n % 12 == 7){
  55. prime[n] = !prime[n];
  56. }
  57. }
  58. void step3(LL x, LL y){
  59. LL n = (3 * x * x) - (y * y);
  60. if(x > y && n <= limit && n % 12 == 11){
  61. prime[n] = !prime[n];
  62. }
  63. }
  64. void loop_y(LL x){
  65. LL y = 1;
  66. while(y * y < limit){
  67. step1(x, y);
  68. step2(x, y);
  69. step3(x, y);
  70. y += 1;
  71. }
  72. }
  73. void loop_x(){
  74. LL x = 1;
  75. while(x * x < limit){
  76. loop_y(x);
  77. x += 1;
  78. }
  79. }
  80. void calc(){
  81. loop_x();
  82. omit_squares();
  83. }
  84. };
  85. Node *generate_trie(std::vector<LL> l){
  86. Node *root = new Node();
  87. for(LL el : l){
  88. Node *head = root;
  89. std::string s = std::to_string(el);
  90. for(char ch : s){
  91. if(head->children.find(ch) == head->children.end()){
  92. head->children[ch] = new Node();
  93. }
  94. head = head->children[ch];
  95. }
  96. head->terminal = true;
  97. }
  98. return root;
  99. }
  100. std::vector<LL> find(LL upper_bound, LL prefix){
  101. Sieve *sieve = new Sieve(upper_bound);
  102. sieve->calc();
  103. std::string str_prefix = std::to_string(prefix);
  104. Node *head = generate_trie(sieve->to_list());
  105. for(char ch : str_prefix){
  106. if(head->children.find(ch) == head->children.end()){
  107. return std::vector<LL>();
  108. }
  109. head = head->children[ch];
  110. }
  111. std::queue<std::pair<Node*, std::string>> q;
  112. std::vector<LL> result;
  113. q.push(std::make_pair(head, str_prefix));
  114. while(!q.empty()){
  115. std::pair<Node*, std::string> top = q.front();
  116. q.pop();
  117. if(top.first->terminal){
  118. result.push_back(std::stoll(top.second));
  119. }
  120. for(std::pair<char, Node*> p : top.first->children){
  121. q.push(std::make_pair(p.second, top.second + p.first));
  122. }
  123. }
  124. std::sort(result.begin(), result.end());
  125. return result;
  126. }
  127. void verify(){
  128. std::vector<LL> left = {2, 23, 29};
  129. std::vector<LL> right = find(100, 2);
  130. if(left != right){
  131. std::cout << "left != right" << std::endl;
  132. exit(1);
  133. }
  134. }
  135. int main(){
  136. const LL UPPER_BOUND = 5000000;
  137. const LL PREFIX = 32338;
  138. verify();
  139. std::vector<LL> results = find(UPPER_BOUND, PREFIX);
  140. std::vector<LL> expected = {323381, 323383, 3233803, 3233809, 3233851, 3233863, 3233873, 3233887, 3233897};
  141. if(results != expected){
  142. std::cout << "results != expected" << std::endl;
  143. exit(1);
  144. }
  145. return 0;
  146. }