#include <iostream>
using namespace std;
#include <cstdlib>
#include <gmp.h>
#include <cstdarg>
#include <vector>
#include <bitset>
#include <string>

template <int N>
void printbit(const bitset<N> &b) {
    if (N % 4 == 0) {
        cout << "'x";
        for (int i = 0; i < b.size(); i = i+4) {
            int n = b[i]*8 + b[i+1]*4 + b[i+2]*2 + b[i+3];
            printf("%X", n);
        }
    }
    else
        cout << "'" <<  b;
}

template <int arr_l, int bit_l>
bitset<arr_l*bit_l> merge(bitset<bit_l>* bs) {
    string s = "";
    for (int i = 0; i < arr_l; i++) {
        s = s + bs[i].to_string();
    }
    return bitset <arr_l*bit_l>(s);
}

int string_of_int (string s) {
    return atoi(s.c_str());
}

string bin_of_hex (string s) {
    string result = "";
    for (int i = 0; i < s.length(); ++i) {
        string digit = s.substr(i, 1);
        char *cp;
        int n = strtol(digit.c_str(), &cp, 16);
        digit = bitset<4>(n).to_string();
        result += digit;
    }
    return result;
}

string dec_of_bin (string s) {
    char *cp = new char [s.length()];
    strcpy(cp, s.c_str());
    mpz_t n;
    mpz_init(n);
    mpz_set_str(n, cp, 2);
    mpz_get_str(cp, 10, n);
    return string(cp);
}

string dec_of_hex (string s) {
    char *cp = new char [2*s.length()];
    strcpy(cp, s.c_str());
    mpz_t n;
    mpz_init(n);
    mpz_set_str(n, cp, 16);
    mpz_get_str(cp, 10, n);
    return string(cp);
}

string add2(string a, string b) {
    mpz_t sum, ia, ib;
    mpz_init(sum);
    mpz_init_set_str(ia, a.c_str(), 10);
    mpz_init_set_str(ib, b.c_str(), 10);
    mpz_add(sum, ia, ib);
    return string(mpz_get_str(NULL, 10, sum));
}

string add(int n, ... ) {
    va_list arguments;                     
    string result = "";
    mpz_t sum;
    mpz_init_set_si(sum, 0);
    va_start (arguments, n);           
    for (int i = 0; i < n; i++) {
        char *c = va_arg (arguments, char*); 
        mpz_t tmp;
        mpz_init_set_str(tmp, c, 10);
        mpz_add(sum, sum, tmp);
    }
    va_end (arguments);
    return string(mpz_get_str(NULL, 10, sum));
}

string mul2(string a, string b) {
    mpz_t sum, ia, ib;
    mpz_init(sum);
    mpz_init_set_str(ia, a.c_str(), 10);
    mpz_init_set_str(ib, b.c_str(), 10);
    mpz_mul(sum, ia, ib);
    return string(mpz_get_str(NULL, 10, sum));
}

string mul(int n, ... ) {
    va_list arguments;                     
    string result = "";
    mpz_t sum;
    mpz_init_set_si(sum, 1);
    va_start (arguments, n);           
    for (int i = 0; i < n; i++) {
        char *c = va_arg (arguments, char*); 
        mpz_t tmp;
        mpz_init_set_str(tmp, c, 10);
        mpz_mul(sum, sum, tmp);
    }
    va_end (arguments);
    return string(mpz_get_str(NULL, 10, sum));
}

string divide(string a, string b) {
    string s;char* c;
    char* a0 = new char [a.length()+1];
    char* b0 = new char [b.length()+1];
    strcpy(a0,a.c_str());
    strcpy(b0,b.c_str());
    mpz_t a1;
    mpz_t a2;
    mpz_t a3;
    mpz_init(a1);
    mpz_init(a2);
    mpz_init(a3);
    mpz_set_str(a1,a0,10);
    mpz_set_str(a2,b0,10);
    mpz_tdiv_q(a3,a1,a2);
    c = mpz_get_str(NULL,10,a3);
    s = string(c);
    delete[] a0;
    delete[] b0;
    delete[] c;
    return s;
}

string subtract(string a, string b) {
    string s;char* c;
    char* a0 = new char [a.length()+1];
    char* b0 = new char [b.length()+1];
    strcpy(a0,a.c_str());
    strcpy(b0,b.c_str());
    mpz_t a1;
    mpz_t a2;
    mpz_t a3;
    mpz_init(a1);
    mpz_init(a2);
    mpz_init(a3);
    mpz_set_str(a1,a0,10);
    mpz_set_str(a2,b0,10);
    mpz_sub(a3,a1,a2);        
    c = mpz_get_str(NULL,10,a3);
    s = string(c);
    delete[] a0;
    delete[] b0;
    delete[] c;
    return s;
  
}

string mod(string a, string b) {
    string s;char* c;
    char* a0 = new char [a.length()+1];
    char* b0 = new char [b.length()+1];
    strcpy(a0,a.c_str());
    strcpy(b0,b.c_str());
    mpz_t a1;
    mpz_t a2;
    mpz_t a3;
    mpz_t a4;
    mpz_init(a1);
    mpz_init(a2);
    mpz_init(a3);
    mpz_init(a4);
    mpz_set_str(a1,a0,10);

    mpz_set_str(a2,b0,10);

    mpz_set_str(a3,"1",10);
    mpz_powm(a4,a1,a3,a2);

    c = mpz_get_str(NULL,10,a4);
    s = string(c);
    delete[] a0;
    delete[] b0;
    delete[] c;
return s;
}

string power(string a, string b) {
   string s;char* c;
   char* a0 = new char [a.length()+1];
   char* b0 = new char [b.length()+1];
   strcpy(a0,a.c_str());
   strcpy(b0,b.c_str());
   mpz_t a1;
   mpz_t a2;
   mpz_t a3;
   unsigned long a4;
   mpz_init(a1);
   mpz_init(a2);
   mpz_init(a3);
   mpz_set_str(a1,a0,10);
   mpz_set_str(a2,b0,10);
   a4 = mpz_get_ui(a2);
   mpz_pow_ui(a3,a1,a4);
   c = mpz_get_str(NULL,10,a3);
   s = string(c);
   delete[] a0;
   delete[] b0;
   delete[] c;
   return s;
  
}

string inverse(string a, string b) {
    string s;char* c;
    char* a0 = new char [a.length()+1];
    char* b0 = new char [b.length()+1];
    strcpy(a0,a.c_str());
    strcpy(b0,b.c_str());
    mpz_t a1;
    mpz_t a2;
    mpz_t a3;
    mpz_init(a1);
    mpz_init(a2);
    mpz_init(a3);
    mpz_set_str(a1,a0,10);
    mpz_set_str(a2,b0,10);
    mpz_invert(a3,a1,a2);
    c = mpz_get_str(NULL,10,a3);
    s = string(c);
    delete[] a0;
    delete[] b0;
    delete[] c;
    return s;
}

bitset<1> not__(bitset<1> b) {
    if (b[0] == 1)
        return bitset<1>(0);
    else
        return bitset<1>(1);
}

bitset<1> less__(string x, string y) {
    mpz_t a, b;
    mpz_init_set_str(a, x.c_str(), 10);
    mpz_init_set_str(b, y.c_str(), 10);
    int c = mpz_cmp(a, b);
    if (c < 0)
        return bitset<1>(1);
    else
        return bitset<1>(0);
}

bitset<1> greater__(string x, string y) {
    mpz_t a, b;
    mpz_init_set_str(a, x.c_str(), 10);
    mpz_init_set_str(b, y.c_str(), 10);
    int c = mpz_cmp(a, b);
    if (c > 0)
        return bitset<1>(1);
    else
        return bitset<1>(0);
}

bitset<1> leq__(string x, string y) {
    mpz_t a, b;
    mpz_init_set_str(a, x.c_str(), 10);
    mpz_init_set_str(b, y.c_str(), 10);
    int c = mpz_cmp(a, b);
    if (c <= 0)
        return bitset<1>(1);
    else
        return bitset<1>(0);
}

bitset<1> geq__(string x, string y) {
    mpz_t a, b;
    mpz_init_set_str(a, x.c_str(), 10);
    mpz_init_set_str(b, y.c_str(), 10);
    int c = mpz_cmp(a, b);
    if (c >= 0)
        return bitset<1>(1);
    else
        return bitset<1>(0);
}

bitset<1> is_prime(string s) {
    mpz_t a;
    mpz_init_set_str(a, s.c_str(), 10);
    int isp = mpz_probab_prime_p(a, 25);
    if (isp == 1 || isp == 2)
        return bitset<1>(1);
    else
        return bitset<1>(0);
}

string next_prime(string s) {
    mpz_t a;
    mpz_t b;
    mpz_init(b);
    mpz_init_set_str(a, s.c_str(), 10);
    int isp = mpz_probab_prime_p(a, 25);
    mpz_nextprime(b, a);
    return string(mpz_get_str(NULL, 10, b));
}