Advertisement
a53

Blitzcatan

a53
Nov 8th, 2018
208
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.52 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <assert.h>
  4.  
  5. #include <utility>
  6. #include <vector>
  7. #include <iterator>
  8. #include <algorithm>
  9.  
  10. #define t_s2pit vector<pair<int, pair<int, int> > >::iterator
  11. #define MAX_N_P 1001 // numarul maxim de numere piramidale
  12. #define MAX_T 1000000001
  13.  
  14. using namespace::std;
  15.  
  16. vector<int> s1p;
  17. vector<pair<int, pair<int, int> > > s2p;
  18. int n_s1p, n_s2p;
  19.  
  20. void print_secrets(vector<int> secrets, FILE* fout) {
  21. fprintf(fout, "%d", (int) secrets.size());
  22. vector<int>:: iterator it;
  23. for(it = secrets.begin(); it != secrets.end(); it++) {
  24. // + 2 pentru ca for loopul pentru numere piramidale
  25. // e 0-indexat dar incepe cu s = 2
  26. fprintf(fout, " %d %d", (*it + 2) % 3, *it + 2);
  27. }
  28. fprintf(fout, "\n");
  29. }
  30.  
  31. bool sum_of_two(t_s2pit *s2p_start,
  32. int nr, vector<int> *secrets) {
  33. t_s2pit pos = lower_bound(*s2p_start, s2p.end(),
  34. make_pair(nr, make_pair(0, 0)));
  35. *s2p_start = pos;
  36. if(pos != s2p.end() && pos->first == nr) {
  37. secrets->push_back(pos->second.first);
  38. secrets->push_back(pos->second.second);
  39. return true;
  40. }
  41.  
  42. return false;
  43. }
  44.  
  45. bool pred(const std::pair<int, std::pair<int, int > > &a,
  46. const std::pair<int, std::pair<int, int > > &b) {
  47. return a.first == b.first;
  48. }
  49.  
  50. int main() {
  51. FILE* in = fopen("blitzcatan.in", "r");
  52. FILE* out = fopen("blitzcatan.out", "w");
  53.  
  54. int n;
  55. fscanf(in, "%d", &n);
  56.  
  57. s1p.reserve(MAX_N_P);
  58. s2p.reserve(MAX_N_P * MAX_N_P);
  59.  
  60. // precalculam toate numerele piramidale <= MAX_T
  61. for(int i = 2; i <= MAX_N_P; i++) {
  62. s1p.push_back((i-1) * i * (i+1));
  63. }
  64. n_s1p = s1p.size();
  65.  
  66. // precalculam toate sumele de 2 numere piramidale
  67. for(int i = 0; i < n_s1p; i++) {
  68. for(int j = i; j < n_s1p && s1p[i] + s1p[j] < MAX_T; j++) {
  69. s2p.push_back(std::make_pair(s1p[i] + s1p[j],
  70. std::make_pair(i, j)));
  71. }
  72. }
  73.  
  74. // sortam s2p si eliminam dublurile
  75. std::sort(s2p.begin(), s2p.end());
  76. s2p.erase(unique(s2p.begin(), s2p.end(), pred), s2p.end());
  77. n_s2p = s2p.size();
  78.  
  79. t_s2pit it_2;
  80. int nr;
  81. std::vector<int> secrets;
  82. for(int i = 0; i < n; i++) {
  83. secrets.clear();
  84. fscanf(in, "%d", &nr);
  85.  
  86. while(1) {
  87. // un numar piramidal
  88. vector<int>::iterator pos = std::lower_bound(s1p.begin(), s1p.end(), nr);
  89. if(pos != s1p.end() && *pos == nr) {
  90. secrets.push_back(pos - s1p.begin());
  91. break;
  92. }
  93.  
  94. // doua numere piramidale
  95. it_2 = s2p.begin();
  96. if(sum_of_two(&it_2, nr, &secrets)) {
  97. break;
  98. }
  99.  
  100. // trei numere piramidale
  101. bool done = false;
  102. it_2 = s2p.begin();
  103. for(int j = n_s1p - 1; j >= 0; j--) {
  104. if (s1p[j] >= nr) continue;
  105. if(sum_of_two(&it_2, nr - s1p[j], &secrets)) {
  106. secrets.push_back(j);
  107. done = true;
  108. break;
  109. }
  110. }
  111. if(done) break;
  112.  
  113. // patru numere piramidale
  114. done = false;
  115. it_2 = s2p.begin();
  116. for(int j = n_s2p - 1; j >= 0; j--) {
  117. if (s2p[j].first >= nr) continue;
  118. if(sum_of_two(&it_2, nr - s2p[j].first, &secrets)) {
  119. pair<int, int> idx = s2p[j].second;
  120. secrets.push_back(idx.first);
  121. secrets.push_back(idx.second);
  122. done = true;
  123. break;
  124. }
  125. }
  126. if(done) break;
  127.  
  128. // nicio solutie
  129. assert(false);
  130. break;
  131. }
  132.  
  133. print_secrets(secrets, out);
  134. }
  135. //printf("%d %d\n", s1p.size(), s2p.size());
  136. return 0;
  137. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement