// Author : Jakub Rożek // Task : // Contest : PA 2024 r // Memory : O(n) // Time : O(n) // Solution : Rozwiązanie wzorcowe #include "dzilib.h" #include <bits/stdc++.h> using namespace std; using LL = long long; template <typename T> using P = pair<T, T>; template <typename T> using VV = vector<vector<T>>; #define FOR(i,a,b) for(int i=(a); i<=(b); ++i) #define FORD(i,a,b) for(int i=(a); i>=(b); --i) #define REP(i,n) for(int i=0; i<(n); ++i) #define all(x) x.begin(), x.end() #define ssize(x) int((x).size()) #ifdef DEBUG template <typename T1, typename T2> auto&operator<<(auto&o,pair<T1,T2>p){return o<<'('<<p.first<<", "<<p.second<<")";} auto operator<<(auto&o,auto x)->decltype(x.end(),o){o<<"{";for(auto e:x)o<<","<<e;return o<<"}";} #define debug(x...) cerr<<"["#x"]: ",[](auto...$){((cerr<<$<<"; "),...)<<endl;}(x) #else #define debug(...) {} #endif // const LL INF = 1'000'000'000'000'000'018; // const int INF = 1'000'000'009; // const LL mod = 1'000'000'007; // const int N = 1'000'000; LL n, q, cc, dokladnosc = 12; unordered_map <LL,LL> dzielniki; LL dwa_do[65]; void odpowiedz(LL x) { Answer(x); } LL get(LL a) { if (dzielniki.count(a) == 0) { dzielniki[a] = Ask(a); --q; } return dzielniki[a]; } void solution() { dzielniki.clear(); LL y, z, a, b, c, ufam, pot; bool zgodny; dwa_do[0] = 1; FOR (i, 1, 62) dwa_do[i] = 2 * dwa_do[i-1]; // poznaje x+0 y = 0; a = get(y); // ustawiam x+y na liczbe pierwszą while (a != 2) { ++y; a = get(y); } // ustawiam x+y na liczbe pierwszą + 1, jest teraz parzysta ++y; a = get(y); // Nasza liczba pierwsza mogla byc = 2 wiec to rozwazam if (a == 2) { // x+y = 3; odpowiedz(3-y); return; } // cofam sie (jak najblizej x) by korzystać z juz policzonych wczesniej wartosci; // pierwsza dobra (podzielna przez 2) liczba; z = y % 2; pot = 2; // podnosimy teraz nasze pot do 2^47 // lub mniej jak szybciej znajdziemy fajny stan (x+y = 2^k) FOR (i, 2, 42) { ufam = 0; y = z; zgodny = true; while (ufam < dokladnosc && ufam > -dokladnosc) { y += pot; zgodny = !zgodny; a = get(y - pot); b = get(y); c = get(y + pot); if (zgodny) { if (a<b && b>c) ++ufam; else if (a>b && b<c) --ufam; } else { if (a<b && b>c) --ufam; else if (a>b && b<c) ++ufam; } } if (ufam < 0) z += pot; // teraz x+z jest pierwszą liczbą po x podzielną przez 2^i; pot *= 2; // Wiem teraz że x+z jest równe pot if (get(z) == i+1) { odpowiedz(pot-z); return; } } while (true) { a = get(z); if (dwa_do[a-1] + z <= cc) { b = get(z + dwa_do[a-1]); if (b == a+1) { odpowiedz(dwa_do[a-1] - z); return; } } z += pot; } return; } int main() { cin.tie(0)->sync_with_stdio(0); int tests = 1; // cin>>tests; tests = GetT(); n = GetN(); q = GetQ(); cc = GetC(); FOR (i, 1, tests) { solution(); } return 0; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | // Author : Jakub Rożek // Task : // Contest : PA 2024 r // Memory : O(n) // Time : O(n) // Solution : Rozwiązanie wzorcowe #include "dzilib.h" #include <bits/stdc++.h> using namespace std; using LL = long long; template <typename T> using P = pair<T, T>; template <typename T> using VV = vector<vector<T>>; #define FOR(i,a,b) for(int i=(a); i<=(b); ++i) #define FORD(i,a,b) for(int i=(a); i>=(b); --i) #define REP(i,n) for(int i=0; i<(n); ++i) #define all(x) x.begin(), x.end() #define ssize(x) int((x).size()) #ifdef DEBUG template <typename T1, typename T2> auto&operator<<(auto&o,pair<T1,T2>p){return o<<'('<<p.first<<", "<<p.second<<")";} auto operator<<(auto&o,auto x)->decltype(x.end(),o){o<<"{";for(auto e:x)o<<","<<e;return o<<"}";} #define debug(x...) cerr<<"["#x"]: ",[](auto...$){((cerr<<$<<"; "),...)<<endl;}(x) #else #define debug(...) {} #endif // const LL INF = 1'000'000'000'000'000'018; // const int INF = 1'000'000'009; // const LL mod = 1'000'000'007; // const int N = 1'000'000; LL n, q, cc, dokladnosc = 12; unordered_map <LL,LL> dzielniki; LL dwa_do[65]; void odpowiedz(LL x) { Answer(x); } LL get(LL a) { if (dzielniki.count(a) == 0) { dzielniki[a] = Ask(a); --q; } return dzielniki[a]; } void solution() { dzielniki.clear(); LL y, z, a, b, c, ufam, pot; bool zgodny; dwa_do[0] = 1; FOR (i, 1, 62) dwa_do[i] = 2 * dwa_do[i-1]; // poznaje x+0 y = 0; a = get(y); // ustawiam x+y na liczbe pierwszą while (a != 2) { ++y; a = get(y); } // ustawiam x+y na liczbe pierwszą + 1, jest teraz parzysta ++y; a = get(y); // Nasza liczba pierwsza mogla byc = 2 wiec to rozwazam if (a == 2) { // x+y = 3; odpowiedz(3-y); return; } // cofam sie (jak najblizej x) by korzystać z juz policzonych wczesniej wartosci; // pierwsza dobra (podzielna przez 2) liczba; z = y % 2; pot = 2; // podnosimy teraz nasze pot do 2^47 // lub mniej jak szybciej znajdziemy fajny stan (x+y = 2^k) FOR (i, 2, 42) { ufam = 0; y = z; zgodny = true; while (ufam < dokladnosc && ufam > -dokladnosc) { y += pot; zgodny = !zgodny; a = get(y - pot); b = get(y); c = get(y + pot); if (zgodny) { if (a<b && b>c) ++ufam; else if (a>b && b<c) --ufam; } else { if (a<b && b>c) --ufam; else if (a>b && b<c) ++ufam; } } if (ufam < 0) z += pot; // teraz x+z jest pierwszą liczbą po x podzielną przez 2^i; pot *= 2; // Wiem teraz że x+z jest równe pot if (get(z) == i+1) { odpowiedz(pot-z); return; } } while (true) { a = get(z); if (dwa_do[a-1] + z <= cc) { b = get(z + dwa_do[a-1]); if (b == a+1) { odpowiedz(dwa_do[a-1] - z); return; } } z += pot; } return; } int main() { cin.tie(0)->sync_with_stdio(0); int tests = 1; // cin>>tests; tests = GetT(); n = GetN(); q = GetQ(); cc = GetC(); FOR (i, 1, tests) { solution(); } return 0; } |