Advertisement
tiom4eg

TOREAD - Power Towers

Dec 15th, 2021
67
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <iostream>
  2. #include <vector>
  3. #include <string>
  4.  
  5. using namespace std;
  6.  
  7. const int max_a = 100;
  8. const double epsilon = 1e-12;
  9.  
  10. enum RESULT { LESS, GREATER, TOP_LESS, TOP_GREATER, TOP_EQUAL };
  11.  
  12. bool is_prime(int n) {
  13.     for (int i = 2; i * i <= n; i++)
  14.         if (n % i == 0)
  15.             return false;
  16.     return true;
  17. }
  18.  
  19. // decomposes n into prime factors
  20. vector <int> factor(int n) {
  21.     vector <int> result;
  22.     for (int k = 2; k <= max_a; k++)
  23.         if (is_prime(k)) {
  24.             int count = 0;
  25.             while (n % k == 0) {
  26.                 n /= k;
  27.                 count++;
  28.             }
  29.             result.push_back(count);
  30.         }
  31.     return result;
  32. }
  33.  
  34. // returns the value of tower a
  35. double evaluate_double(const vector <int> &a) {
  36.     double result = 1.0;
  37.     // check for overflow is necessary!!!
  38.     for (int i = a.size() - 1; i >= 0; i--)
  39.         result = pow(a[i], result);
  40.     return result;
  41. }
  42.  
  43. // returns the value of tower a
  44. int evaluate_int(const vector <int> &a) {
  45.     int result = 1;
  46.     // check for overflow is necessary!!!
  47.     for (int i = a.size() - 1; i >= 0; i--) {
  48.         int new_result = 1;
  49.         for (int j = 0; j < result; j++)
  50.             new_result *= a[i];
  51.         result = new_result;
  52.     }
  53.     return result;
  54. }
  55.  
  56. // returns the logarithm of tower a
  57. double evaluate_log(const vector <int> &a) {
  58.     if (a.size() == 0)
  59.         return 0.0;
  60.     else {
  61.         vector <int> new_a(++a.begin(), a.end());
  62.         return log((double)a[0]) * evaluate_double(new_a);
  63.     }
  64. }
  65.  
  66. int gcd(int a, int b) {
  67.     return b == 0 ? a : gcd(b, a % b);
  68. }
  69.  
  70. // compares real number to a tower
  71. // x >= 1.0
  72. bool is_less(double x, const vector <int> &a) {
  73.     for (int i = 0; i < a.size(); i++) {
  74.         x = log(x) / log((double)a[i]);
  75.         if (x < 1)
  76.             return true;
  77.     }
  78.     return false;
  79. }
  80.  
  81. // returns true if a * p == b * q
  82. // a, b - towers
  83. // p, q >= 1
  84. bool is_equal(const vector <int> &a, int p, const vector <int> &b, int q) {
  85.     if (a.size() == 0 && b.size() == 0)
  86.         return p == q;
  87.     else if (a.size() == 0)
  88.         // a == 1
  89.         // p >= b && p == b * q
  90.         // multiply p by 2 to avoid rounding problems
  91.         return !is_less(2 * p, b) && p == evaluate_int(b) * q;
  92.     else if (b.size() == 0)
  93.         // b == 1
  94.         // q >= a && q == a * p
  95.         // multiply q by 2 to avoid rounding problems
  96.         return !is_less(2 * q, a) && q == evaluate_int(a) * p;
  97.     vector <int> f_p = factor(p);
  98.     vector <int> f_a = factor(a[0]);
  99.     vector <int> f_q = factor(q);
  100.     vector <int> f_b = factor(b[0]);
  101.     vector <int> new_a(a.begin() + 1, a.end());
  102.     vector <int> new_b(b.begin() + 1, b.end());
  103.     int c = -1, d = -1;
  104.     // check each prime factor
  105.     for (int i = 0; i < f_p.size(); i++) {
  106.         if (f_p[i] != f_q[i]) {
  107.             int value_a = evaluate_int(new_a);
  108.             int value_b = evaluate_int(new_b);
  109.             // check for overflow!!!
  110.             if (f_a[i] * value_a + f_p[i] != f_b[i] * value_b + f_q[i])
  111.                 return false;
  112.         }
  113.         else if ((f_a[i] == 0) != (f_b[i] == 0))
  114.             return false;
  115.         else if (f_a[i] != 0 && f_b[i] != 0) {
  116.             // f_a[i] >= 1, f_b[i] >= 1
  117.             int g = gcd(f_a[i], f_b[i]);
  118.             int new_c = f_a[i] / g;
  119.             int new_d = f_b[i] / g;
  120.             if (c == -1 && d == -1) {
  121.                 c = new_c;
  122.                 d = new_d;
  123.             }
  124.             else if (c != new_c || d != new_d)
  125.                 return false;
  126.         }
  127.     }
  128.     if (c == -1 && d == -1)
  129.         return true;
  130.     else
  131.         return is_equal(new_a, c, new_b, d);
  132. }
  133.  
  134. // a.size(), b.size() >= 1
  135. // returns LESS if the whole tower a is less than b
  136. // returns GREATER if the whole tower a is greater than b
  137. // returns TOP_LESS if the top part of tower a is less than the top part of tower b
  138. // returns TOP_GREATER if the top part of tower a is greater than the top part of tower b
  139. // returns TOP_EQUAL if the top part of tower a equals the top part of tower b
  140. RESULT solve(const vector <int> &a, const vector <int> &b) {
  141.     double x = a[0];
  142.     double y = b[0];
  143.     vector <int> new_a(a.begin() + 1, a.end());
  144.     vector <int> new_b(b.begin() + 1, b.end());
  145.     // consider the case where new_a == new_b
  146.     if (is_equal(new_a, 1, new_b, 1)) {
  147.         double d = log(log(x)) - log(log(y));
  148.         if (x == y)
  149.             return TOP_EQUAL;
  150.         else if (d > epsilon && is_less(log(10.0) / (d * log(y)), new_a))
  151.             return GREATER;
  152.         else if (d < -epsilon && is_less(log(10.0) / (-d * log(x)), new_a))
  153.             return LESS;
  154.         else if (d > 0)
  155.             return TOP_GREATER;
  156.         else
  157.             return TOP_LESS;
  158.     }
  159.     else {
  160.         double log_x_a = evaluate_log(new_a) + log(log(x));
  161.         double log_y_b = evaluate_log(new_b) + log(log(y));
  162.         double d = log_x_a - log_y_b;
  163.         if (d > epsilon && log_y_b > log(log(10.0)) - log(d))
  164.             return GREATER;
  165.         else if (d < -epsilon && log_x_a > log(log(10.0)) - log(-d))
  166.             return LESS;
  167.         else if (is_equal(a, 1, b, 1))
  168.             return TOP_EQUAL;
  169.         else if (d > 0)
  170.             return TOP_GREATER;
  171.         else
  172.             return TOP_LESS;
  173.     }
  174. }
  175.  
  176. vector <int> read_tower(istream &in) {
  177.     int n;
  178.     in >> n;
  179.     vector <int> result(n);
  180.     for (int i = 0; i < n; i++)
  181.         in >> result[i];
  182.     // normalize tower (remove all ones)
  183.     for (int i = 0; i < result.size(); i++)
  184.         if (result[i] == 1) {
  185.             result.erase(result.begin() + i, result.end());
  186.             break;
  187.         }
  188.     return result;
  189. }
  190.  
  191. int main() {
  192.     vector <int> a = read_tower(cin);
  193.     vector <int> b = read_tower(cin);
  194.     // each element of towers is >= 2 and <= max_a
  195.     RESULT ans;
  196.     if (a.size() >= b.size() + 3)
  197.         ans = GREATER;
  198.     else if (b.size() >= a.size() + 3)
  199.         ans = LESS;
  200.     else if (a.size() == 0 && b.size() == 0)
  201.         ans = TOP_EQUAL;
  202.     else if (a.size() == 0 && b.size() != 0)
  203.         ans = LESS;
  204.     else if (b.size() == 0 && a.size() != 0)
  205.         ans = GREATER;
  206.     else {
  207.         for (int i = min(a.size() - 1, b.size() - 1); i >= 0; i--) {
  208.             vector <int> new_a(a.begin() + i, a.end());
  209.             vector <int> new_b(b.begin() + i, b.end());
  210.             ans = solve(new_a, new_b);
  211.             if (ans == LESS || ans == GREATER)
  212.                 break;
  213.         }
  214.     }
  215.     if (ans == LESS || ans == TOP_LESS)
  216.         cout << "Less" << endl;
  217.     else if (ans == GREATER || ans == TOP_GREATER)
  218.         cout << "Greater" << endl;
  219.     else
  220.         cout << "Equal" << endl;
  221.     return 0;
  222. }
  223.  
  224. // Input format:
  225. // n
  226. // a1 a2 ... an
  227. // m
  228. // b1 b2 ... bm
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement