#include <stdio.h>
#include <dlfcn.h>
#include <cassert>
#include <gmp.h>
extern "C" {
// SPOJ, codechef, ideone (64-bit)
const char* gmp_path = "/usr/lib/x86_64-linux-gnu/libgmp.so.10";
void* __libc_dlopen_mode(const char* x, int y);
void* __libc_dlsym(void* x, const char* y);
#define DLOPEN __libc_dlopen_mode
#define DLSYM __libc_dlsym
}
namespace gmp {
void* p = DLOPEN(gmp_path, 2);
void* get(const char* name) { return DLSYM(p, name); }
#define D(name) const auto my_##name = (decltype(name)*) get("__g" #name)
D(mpz_init); D(mpz_init_set_ui); D(mpz_init_set); D(mpz_init_set_str);
D(mpz_clear);
D(mpz_set); D(mpz_set_ui);
D(mpz_swap);
D(mpz_set_str); D(mpz_get_str);
D(mpz_inp_str); D(mpz_out_str);
D(mpz_neg);
D(mpz_add); D(mpz_add_ui);
D(mpz_sub); D(mpz_sub_ui);
D(mpz_mul); D(mpz_mul_ui); D(mpz_mul_2exp);
D(mpz_tdiv_r); D(mpz_tdiv_q); D(mpz_tdiv_qr); D(mpz_tdiv_q_2exp);
D(mpz_divexact); D(mpz_divexact_ui);
D(mpz_pow_ui);
D(mpz_sqrt);
D(mpz_xor); D(mpz_and); D(mpz_ior);
D(mpz_cmp);
#undef D
struct mpz {
mpz() { my_mpz_init(n); }
mpz(mp_limb_t v) { my_mpz_init_set_ui(n, v); }
mpz(const mpz& v) { my_mpz_init_set(n, v.n); }
mpz(const char* str) { my_mpz_init_set_str(n, str, 10); }
~mpz() { my_mpz_clear(n); }
void set(const mpz& rhs) { my_mpz_set(n, rhs.n); }
void set_ui(mp_limb_t i) { my_mpz_set_ui(n, i); }
void inp_str(FILE* fp=stdin, int base=10) { my_mpz_inp_str(n, fp, base); }
void set_str(char* str, mp_limb_t base=10) { my_mpz_set_str(n, str, base); }
void get_str(char* str, mp_limb_t base=10) { my_mpz_get_str(str, base, n); }
void print(FILE* fp=stdout) { my_mpz_out_str(fp, 10, n); }
void println(FILE* fp=stdout) { print(fp); fprintf(fp, "\n"); }
static void add(mpz& c, mpz& a, mpz& b) { my_mpz_add(c.n, a.n, b.n); }
static void mul(mpz& c, mpz& a, mpz& b) { my_mpz_mul(c.n, a.n, b.n); }
static void mul_ui(mpz& c, mpz& a, mp_limb_t b) { my_mpz_mul_ui(c.n, a.n, b); }
static void sqrt(mpz& dest, mpz& src) { my_mpz_sqrt(dest.n, src.n); }
static void divmod(mpz& q, mpz& r, mpz& n, mpz& d) { my_mpz_tdiv_qr(q.n, r.n, n.n, d.n); }
static void div(mpz& q, mpz& n, mpz& d) { my_mpz_tdiv_q(q.n, n.n, d.n); }
static void divexact(mpz &q, mpz& n, mpz& d) { my_mpz_divexact(q.n, n.n, d.n); }
static void mod(mpz& r, mpz& n, mpz& d) { my_mpz_tdiv_r(r.n, n.n, d.n); }
static void swap(mpz& a, mpz& b) { my_mpz_swap(a.n, b.n); }
void negate() { my_mpz_neg(n, n); }
void pow_ui(mp_limb_t e) { my_mpz_pow_ui(n, n, e); }
void divexact_ui(mp_limb_t c) { my_mpz_divexact_ui(n, n, c); }
void divexact(mpz& rhs) { my_mpz_divexact(n, n, rhs.n); }
bool operator == (mpz& rhs) { return my_mpz_cmp(n, rhs.n) == 0; }
bool operator <= (mpz& rhs) { return my_mpz_cmp(n, rhs.n) <= 0; }
bool operator < (mpz& rhs) { return my_mpz_cmp(n, rhs.n) < 0; }
mpz& operator *= (mpz& rhs) { my_mpz_mul(n, n, rhs.n); return *this; }
mpz& operator *= (mp_limb_t rhs) { my_mpz_mul_ui(n, n, rhs); return *this; }
mpz& operator <<= (int s) { my_mpz_mul_2exp(n, n, s); return *this; }
mpz& operator >>= (int s) { my_mpz_tdiv_q_2exp(n, n, s); return *this; }
mpz_t n;
};
} // namespace gmp
int main() {
using namespace gmp;
mpz n;
n.set_ui(5);
n.pow_ui(100);
n.println();
return 0;
}
ICAgICNpbmNsdWRlIDxzdGRpby5oPgogICAgICNpbmNsdWRlIDxkbGZjbi5oPgogICAgICNpbmNsdWRlIDxjYXNzZXJ0PgogICAgI2luY2x1ZGUgPGdtcC5oPgogICAgIAogICAgZXh0ZXJuICJDIiB7CiAgICAgIC8vIFNQT0osIGNvZGVjaGVmLCBpZGVvbmUgKDY0LWJpdCkKICAgICAgY29uc3QgY2hhciogZ21wX3BhdGggPSAiL3Vzci9saWIveDg2XzY0LWxpbnV4LWdudS9saWJnbXAuc28uMTAiOwogICAgICB2b2lkKiBfX2xpYmNfZGxvcGVuX21vZGUoY29uc3QgY2hhciogeCwgaW50IHkpOwogICAgICB2b2lkKiBfX2xpYmNfZGxzeW0odm9pZCogeCwgY29uc3QgY2hhciogeSk7CiAgICAgICNkZWZpbmUgRExPUEVOIF9fbGliY19kbG9wZW5fbW9kZQogICAgICAjZGVmaW5lIERMU1lNIF9fbGliY19kbHN5bQogICAgfQogICAgIAogICAgbmFtZXNwYWNlIGdtcCB7CiAgICAgCiAgICB2b2lkKiBwID0gRExPUEVOKGdtcF9wYXRoLCAyKTsKICAgIHZvaWQqIGdldChjb25zdCBjaGFyKiBuYW1lKSB7IHJldHVybiBETFNZTShwLCBuYW1lKTsgfQogICAgI2RlZmluZSBEKG5hbWUpIGNvbnN0IGF1dG8gbXlfIyNuYW1lID0gKGRlY2x0eXBlKG5hbWUpKikgZ2V0KCJfX2ciICNuYW1lKQogICAgRChtcHpfaW5pdCk7IEQobXB6X2luaXRfc2V0X3VpKTsgRChtcHpfaW5pdF9zZXQpOyBEKG1wel9pbml0X3NldF9zdHIpOwogICAgRChtcHpfY2xlYXIpOyAKICAgIEQobXB6X3NldCk7IEQobXB6X3NldF91aSk7IAogICAgRChtcHpfc3dhcCk7CiAgICBEKG1wel9zZXRfc3RyKTsgRChtcHpfZ2V0X3N0cik7CiAgICBEKG1wel9pbnBfc3RyKTsgRChtcHpfb3V0X3N0cik7CiAgICAgCiAgICBEKG1wel9uZWcpOwogICAgRChtcHpfYWRkKTsgRChtcHpfYWRkX3VpKTsKICAgIEQobXB6X3N1Yik7IEQobXB6X3N1Yl91aSk7CiAgICBEKG1wel9tdWwpOyBEKG1wel9tdWxfdWkpOyBEKG1wel9tdWxfMmV4cCk7CiAgICBEKG1wel90ZGl2X3IpOyBEKG1wel90ZGl2X3EpOyBEKG1wel90ZGl2X3FyKTsgRChtcHpfdGRpdl9xXzJleHApOwogICAgRChtcHpfZGl2ZXhhY3QpOyBEKG1wel9kaXZleGFjdF91aSk7CiAgICBEKG1wel9wb3dfdWkpOyAKICAgIEQobXB6X3NxcnQpOwogICAgIAogICAgRChtcHpfeG9yKTsgRChtcHpfYW5kKTsgRChtcHpfaW9yKTsKICAgIEQobXB6X2NtcCk7CiAgICAjdW5kZWYgRAogICAgIAogICAgc3RydWN0IG1weiB7CiAgICAgIG1weigpIHsgbXlfbXB6X2luaXQobik7IH0KICAgICAgbXB6KG1wX2xpbWJfdCB2KSB7IG15X21wel9pbml0X3NldF91aShuLCB2KTsgfQogICAgICBtcHooY29uc3QgbXB6JiB2KSB7IG15X21wel9pbml0X3NldChuLCB2Lm4pOyB9CiAgICAgIG1weihjb25zdCBjaGFyKiBzdHIpIHsgbXlfbXB6X2luaXRfc2V0X3N0cihuLCBzdHIsIDEwKTsgfQogICAgICB+bXB6KCkgeyBteV9tcHpfY2xlYXIobik7IH0KICAgICAKICAgICAgdm9pZCBzZXQoY29uc3QgbXB6JiByaHMpIHsgbXlfbXB6X3NldChuLCByaHMubik7IH0KICAgICAgdm9pZCBzZXRfdWkobXBfbGltYl90IGkpIHsgbXlfbXB6X3NldF91aShuLCBpKTsgfQogICAgICB2b2lkIGlucF9zdHIoRklMRSogZnA9c3RkaW4sIGludCBiYXNlPTEwKSB7IG15X21wel9pbnBfc3RyKG4sIGZwLCBiYXNlKTsgfQogICAgICB2b2lkIHNldF9zdHIoY2hhciogc3RyLCBtcF9saW1iX3QgYmFzZT0xMCkgeyBteV9tcHpfc2V0X3N0cihuLCBzdHIsIGJhc2UpOyB9CiAgICAgIHZvaWQgZ2V0X3N0cihjaGFyKiBzdHIsIG1wX2xpbWJfdCBiYXNlPTEwKSB7IG15X21wel9nZXRfc3RyKHN0ciwgYmFzZSwgbik7IH0KICAgICAKICAgICAgdm9pZCBwcmludChGSUxFKiBmcD1zdGRvdXQpIHsgbXlfbXB6X291dF9zdHIoZnAsIDEwLCBuKTsgfQogICAgICB2b2lkIHByaW50bG4oRklMRSogZnA9c3Rkb3V0KSB7IHByaW50KGZwKTsgZnByaW50ZihmcCwgIlxuIik7IH0KICAgICAKICAgICAgc3RhdGljIHZvaWQgYWRkKG1weiYgYywgbXB6JiBhLCBtcHomIGIpIHsgbXlfbXB6X2FkZChjLm4sIGEubiwgYi5uKTsgfQogICAgICBzdGF0aWMgdm9pZCBtdWwobXB6JiBjLCBtcHomIGEsIG1weiYgYikgeyBteV9tcHpfbXVsKGMubiwgYS5uLCBiLm4pOyB9CiAgICAgIHN0YXRpYyB2b2lkIG11bF91aShtcHomIGMsIG1weiYgYSwgbXBfbGltYl90IGIpIHsgbXlfbXB6X211bF91aShjLm4sIGEubiwgYik7IH0KICAgICAgc3RhdGljIHZvaWQgc3FydChtcHomIGRlc3QsIG1weiYgc3JjKSB7IG15X21wel9zcXJ0KGRlc3Qubiwgc3JjLm4pOyB9CiAgICAgIHN0YXRpYyB2b2lkIGRpdm1vZChtcHomIHEsIG1weiYgciwgbXB6JiBuLCBtcHomIGQpIHsgbXlfbXB6X3RkaXZfcXIocS5uLCByLm4sIG4ubiwgZC5uKTsgfQogICAgICBzdGF0aWMgdm9pZCBkaXYobXB6JiBxLCBtcHomIG4sIG1weiYgZCkgeyBteV9tcHpfdGRpdl9xKHEubiwgbi5uLCBkLm4pOyB9CiAgICAgIHN0YXRpYyB2b2lkIGRpdmV4YWN0KG1weiAmcSwgbXB6JiBuLCBtcHomIGQpIHsgbXlfbXB6X2RpdmV4YWN0KHEubiwgbi5uLCBkLm4pOyB9CiAgICAgIHN0YXRpYyB2b2lkIG1vZChtcHomIHIsIG1weiYgbiwgbXB6JiBkKSB7IG15X21wel90ZGl2X3Ioci5uLCBuLm4sIGQubik7IH0KICAgICAgc3RhdGljIHZvaWQgc3dhcChtcHomIGEsIG1weiYgYikgeyBteV9tcHpfc3dhcChhLm4sIGIubik7IH0KICAgICAKICAgICAgdm9pZCBuZWdhdGUoKSB7IG15X21wel9uZWcobiwgbik7IH0KICAgICAgdm9pZCBwb3dfdWkobXBfbGltYl90IGUpIHsgbXlfbXB6X3Bvd191aShuLCBuLCBlKTsgfQogICAgICB2b2lkIGRpdmV4YWN0X3VpKG1wX2xpbWJfdCBjKSB7IG15X21wel9kaXZleGFjdF91aShuLCBuLCBjKTsgfQogICAgICB2b2lkIGRpdmV4YWN0KG1weiYgcmhzKSB7IG15X21wel9kaXZleGFjdChuLCBuLCByaHMubik7IH0KICAgICAgYm9vbCBvcGVyYXRvciA9PSAobXB6JiByaHMpIHsgcmV0dXJuIG15X21wel9jbXAobiwgcmhzLm4pID09IDA7IH0KICAgICAgYm9vbCBvcGVyYXRvciA8PSAobXB6JiByaHMpIHsgcmV0dXJuIG15X21wel9jbXAobiwgcmhzLm4pIDw9IDA7IH0KICAgICAgYm9vbCBvcGVyYXRvciA8IChtcHomIHJocykgeyByZXR1cm4gbXlfbXB6X2NtcChuLCByaHMubikgPCAwOyB9CiAgICAgIG1weiYgb3BlcmF0b3IgKj0gKG1weiYgcmhzKSB7IG15X21wel9tdWwobiwgbiwgcmhzLm4pOyByZXR1cm4gKnRoaXM7IH0KICAgICAgbXB6JiBvcGVyYXRvciAqPSAobXBfbGltYl90IHJocykgeyBteV9tcHpfbXVsX3VpKG4sIG4sIHJocyk7IHJldHVybiAqdGhpczsgfQogICAgICBtcHomIG9wZXJhdG9yIDw8PSAoaW50IHMpIHsgbXlfbXB6X211bF8yZXhwKG4sIG4sIHMpOyByZXR1cm4gKnRoaXM7IH0KICAgICAgbXB6JiBvcGVyYXRvciA+Pj0gKGludCBzKSB7IG15X21wel90ZGl2X3FfMmV4cChuLCBuLCBzKTsgcmV0dXJuICp0aGlzOyB9CiAgICAgCiAgICAgIG1wel90IG47CiAgICB9OwogICAgIAogICAgfSAvLyBuYW1lc3BhY2UgZ21wCiAgICAgCiAgICBpbnQgbWFpbigpIHsKCiAgICAgIHVzaW5nIG5hbWVzcGFjZSBnbXA7CiAgICAgIG1weiBuOwogICAgICBuLnNldF91aSg1KTsKICAgICAgbi5wb3dfdWkoMTAwKTsKICAgICAgbi5wcmludGxuKCk7CiAgICAgIHJldHVybiAwOwogICAgfQogICAgIA==