Advertisement
Mlxa

IATI 2017 SHOPPING или решение длинного Диофантова ур-я.

Nov 20th, 2018
155
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.24 KB | None | 0 0
  1. #pragma GCC optimize("O2")
  2. #define NDEBUG
  3. #include <bits/stdc++.h>
  4. using namespace std;
  5.  
  6. using Int   = long long;
  7. using Real  = long double;
  8. using Char  = unsigned char;
  9. using Bool  = unsigned char;
  10.  
  11. const Int INT_INF   = 2E18;
  12. const Int BOUND     = 1E9;
  13. const Int N         = 2E5;
  14.  
  15. Int extended_gcd(Int a, Int & x, Int b, Int & y)
  16. {
  17.     if (a == 0)
  18.     {
  19.         x = 0;
  20.         y = 1;
  21.         return b;
  22.     }
  23.     Int x1, y1, g;
  24.     g = extended_gcd(b % a, x1, a, y1);
  25.     x = y1 - (b / a) * x1;
  26.     y = x1;
  27.     return g;
  28. }
  29.  
  30. Int floor_div(Int a, Int b)
  31. {
  32.     if (b < 0)
  33.     {
  34.         a = -a;
  35.         b = -b;
  36.     }
  37.     if (a >= 0)
  38.     {
  39.         return a / b;
  40.     }
  41.     return (a - b + 1) / b;
  42. }
  43.  
  44. Int ceil_div(Int a, Int b)
  45. {
  46.     if (b < 0)
  47.     {
  48.         a = -a;
  49.         b = -b;
  50.     }
  51.     if (a >= 0)
  52.     {
  53.         return (a + b - 1) / b;
  54.     }
  55.     return a / b;
  56. }
  57.  
  58. void solve_diofant(Int a, Int & x, Int b, Int & y, Int c)
  59. {
  60.     Int g = extended_gcd(a, x, b, y);
  61.  
  62.     Int x0 = x * c;
  63.     Int y0 = y * c;
  64.     Int dx = (b / g);
  65.     Int dy = -(a / g);
  66.  
  67.     /// x = x0 + k * dx
  68.     /// y = y0 + k * dy
  69.  
  70.     Int min_k = -INT_INF, max_k = INT_INF;
  71.  
  72.     /// x0 + k * dx >= -BOUND
  73.     /// y0 + k * dy >= -BOUND
  74.     if (dx > 0)
  75.     {
  76.         min_k = max(min_k, ceil_div(-x0 - BOUND, dx));
  77.     }
  78.     else
  79.     {
  80.         max_k = min(max_k, floor_div(-x0 - BOUND, dx));
  81.     }
  82.     if (dy > 0)
  83.     {
  84.         min_k = max(min_k, ceil_div(-y0 - BOUND, dy));
  85.     }
  86.     else
  87.     {
  88.         max_k = min(max_k, floor_div(-y0 - BOUND, dy));
  89.     }
  90.  
  91.     /// x0 + k * dx <= BOUND
  92.     /// y0 + k * dy <= BOUND
  93.     if (dx > 0)
  94.     {
  95.         max_k = min(max_k, floor_div(BOUND - x0, dx));
  96.     }
  97.     else
  98.     {
  99.         min_k = max(min_k, ceil_div(BOUND - x0, dx));
  100.     }
  101.     if (dy > 0)
  102.     {
  103.         max_k = min(max_k, floor_div(BOUND - y0, dy));
  104.     }
  105.     else
  106.     {
  107.         min_k = max(min_k, ceil_div(BOUND - y0, dy));
  108.     }
  109.  
  110.     assert(min_k <= max_k);
  111.  
  112.     Int k = (min_k + max_k) / 2;
  113.  
  114.     x = x0 + k * dx;
  115.     y = y0 + k * dy;
  116. }
  117.  
  118. Int answer[N];
  119. int a[N];
  120.  
  121. const Int L = 20;
  122.  
  123. int t[L][N];
  124. Int bin_log[N];
  125.  
  126. void build()
  127. {
  128.     bin_log[1] = 0;
  129.     for (Int i = 2; i < N; ++i)
  130.     {
  131.         bin_log[i] = bin_log[i / 2] + 1;
  132.     }
  133.  
  134.     fill(t[0], t[0] + N * L, 0);
  135.     copy(a, a + N, t[0]);
  136.  
  137.     for (Int i = 1; i < L; ++i)
  138.     {
  139.         for (Int j = 0; j + (1LL << i) <= N; ++j)
  140.         {
  141.             t[i][j] = __gcd(t[i - 1][j], t[i - 1][j + (1LL << (i - 1))]);
  142.         }
  143.     }
  144. }
  145.  
  146. Int range_gcd(Int l, Int r)
  147. {
  148.     Int i = bin_log[r - l];
  149.     return __gcd(t[i][l], t[i][r - (1LL << i)]);
  150. }
  151.  
  152. void recursive_solve(Int l, Int r, Int c)
  153. {
  154.     if (r - l == 1)
  155.     {
  156.         answer[l] = c;
  157.         return;
  158.     }
  159.     Int m = (l + r) / 2;
  160.     Int g1 = range_gcd(l, m);
  161.     Int g2 = range_gcd(m, r);
  162.     Int x, y;
  163.  
  164.     solve_diofant(g1, x, g2, y, c);
  165.  
  166.     recursive_solve(l, m, x);
  167.     recursive_solve(m, r, y);
  168. }
  169.  
  170.  
  171. void solve()
  172. {
  173.     Int n, c, g = 0;
  174.     cin >> n;
  175.  
  176.     fill(a, a + N, 0);
  177.  
  178.     for (Int i = 0; i < n; ++i)
  179.     {
  180.         cin >> a[i];
  181.     }
  182.  
  183.     build();
  184.  
  185.     g = range_gcd(0, n);
  186.  
  187.     cin >> c;
  188.  
  189.     if (c % g)
  190.     {
  191.         cout << "No solutions\n";
  192.         return;
  193.     }
  194.  
  195.     recursive_solve(0, n, c / g);
  196.  
  197.     for (Int i = 0; i < n; ++i)
  198.     {
  199.         cout << answer[i] << ' ';
  200.     }
  201.     cout << '\n';
  202. }
  203.  
  204. int main()
  205. {
  206.     ios::sync_with_stdio(false);
  207.     cin.tie(nullptr);
  208.     cout.tie(nullptr);
  209.  
  210.     Int tests;
  211.     cin >> tests;
  212.  
  213.     while (tests--)
  214.     {
  215.         solve();
  216.     }
  217.  
  218.     return 0;
  219. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement