#include <iostream>
#include <string>
#include <cctype>
#include <cassert>
#include <exception>
enum {
BIT = 4, // for test
// BIT = 30,
CMASK = 1 << BIT,
BMASK = CMASK - 1
};
namespace QZ {
class mpz_class {
private:
int n;
int *b;
private:
friend mpz_class sub(mpz_class const &a, mpz_class const &b);
friend mpz_class mul2(mpz_class const &a, mpz_class const &b);
friend void div2(mpz_class const &a, mpz_class const &b, mpz_class &q, mpz_class &r);
static bool iszero(mpz_class &n);
static void LeftShift(mpz_class &a);
static void RightShift(mpz_class &a, int &lsb);
static void LeftShift2(int &msb, mpz_class &a);
static void LeftShift3(mpz_class &a, int msb);
public:
mpz_class();
mpz_class(const mpz_class &ob);
mpz_class(const unsigned long n);
~mpz_class();
mpz_class &operator=(mpz_class const n);
friend bool operator==(mpz_class const &a, mpz_class const &b);
friend bool operator!=(mpz_class const &a, mpz_class const &b) { return !(a == b); }
friend mpz_class operator+(mpz_class const &a, mpz_class const &b);
friend mpz_class operator-(mpz_class const &a, mpz_class const &b) { return sub(a, b); }
friend mpz_class operator*(mpz_class const &a, mpz_class const &b) { return mul2(a, b); }
friend mpz_class operator/(mpz_class const &a, mpz_class const &b) { mpz_class q, r; div2(a, b, q, r); return q; }
friend mpz_class operator%(mpz_class const &a, mpz_class const &b) { mpz_class q, r; div2(a, b, q, r); return r; }
friend bool operator<(mpz_class const &a, mpz_class const &b);
friend bool operator<=(mpz_class const &a, mpz_class const &b) { return (a < b) ? true : (a == b) ? true : false; }
friend bool operator>(mpz_class const &a, mpz_class const &b) { return (a < b) ? false : (a == b) ? false : true; }
friend bool operator>=(mpz_class const &a, mpz_class const &b) { return (a < b) ? false : (a == b) ? true : true; }
mpz_class &operator+=(mpz_class const &n) { *this = *this + n; return *this; }
mpz_class &operator-=(mpz_class const &n) { *this = *this - n; return *this; }
mpz_class &operator*=(mpz_class const &n) { *this = *this * n; return *this; }
mpz_class &operator/=(mpz_class const &n) { *this = *this / n; return *this; }
mpz_class &operator%=(mpz_class const &n) { *this = *this % n; return *this; }
friend std::ostream &operator<<(std::ostream &stream, mpz_class c);
void dump() const {
std::cout << "n = " << this->n << ": ";
for (int i = 0; i < this->n; i++)
std::cout << i << ":" << this->b[i] << ",";
std::cout << std::endl;
}
/*--------------------------------------------------------*/
public:
void print_tmp1(int prec);
void bit_output(int i, int K); /* i: 現在着目している桁, k:一つの桁でビットを表示する個数 */
}; /* class QZ::mpz_class */
void mpz_class::bit_output(int i, int K) { /* i: 現在着目している桁, k:一つの桁でビットを表示する個数 */
int pbuf = 0;
int mask = 1;
for (int j = 0; j < K; j++) {
if (((this->b[i]) & mask) > 0) {
pbuf = (pbuf | 0x01);
} else {
}
pbuf = (pbuf << 1);
mask = (mask << 1);
}
pbuf = (pbuf >> 1);
for (int j = 0; j < K; j++) {
if ((pbuf & 0x01) > 0)
std::cout << '1';
else
std::cout << '0';
pbuf = (pbuf >> 1);
}
}
int f(int n, int BIT) { /* f(1)=1, f(2)=2, f(3)=3, f(4)=4, f(5)=1, f(6)=2, f(7)=3, f(8)=4,f(9)=1,f(10)=2 etc */
int s;
return ((s = (n % BIT)) == 0) ? BIT : s;
}
void mpz_class::print_tmp1(int prec) {
int max_need_buff_position = (prec - 1) / 4;
for (int i = max_need_buff_position; i >= 0 /* i is signed */; --i) {
if (i == max_need_buff_position && i > this->n - 1) { /* 要求される精度におけるMSB 桁で、メモリ上に存在しない */
for (int j = 0; j < f(prec, BIT); j++)
std::cout << "0";
} else if (i == max_need_buff_position && i <= this->n - 1) { /* 要求される精度におけるMSBを含む桁で、メモリ上に存在する */
this->QZ::mpz_class::bit_output(i, f(prec, BIT));
} else if (i < max_need_buff_position && i > this->n - 1) { /* 要求される精度におけるMSB 桁未満で、メモリ上に存在しない */
for (int j = 0; j < BIT; j++)
std::cout << "0";
} else if (i < max_need_buff_position && i <= this->n - 1) { /* 要求される精度におけるMSB 桁未満で、メモリ上に存在する */
this->QZ::mpz_class::bit_output(i, BIT);
} else { /* for debug */
assert(0); /* not reach */
}
}
std::cout << std::endl;
}
/*--------------------------------------------------------*/
mpz_class::mpz_class() {
this->n = 1;
this->b = new int[1];
this->b[0] = 0;
}
mpz_class::mpz_class(const mpz_class &ob) {
this->n = ob.n;
if (ob.n == 0) {
this->b = 0;
} else {
this->b = new int[ob.n];
for (int i = 0; i < ob.n; i++)
this->b[i] = ob.b[i];
}
}
mpz_class::mpz_class(const unsigned long c) {
if (c <= 0) {
this->n = 1;
this->b = new int[1];
this->b[0] = 0;
} else {
int *newbody;
int i, j, r, cc, pos;
this->b = 0;
this->n = 0;
cc = c;
while (cc > 0) {
r = 0;
pos = 1;
for (i = 0; i < BIT; i++) {
if ((cc & 1) != 0) {
r = (r | pos);
} else {
}
pos = pos * 2;
cc = cc / 2;
}
newbody = new int[this->n + 1];
for (j = 0; j < this->n; j++)
newbody[j] = this->b[j];
newbody[j] = r; /* j == this->n */
delete this->b;
this->b = newbody;
this->n++;
}
}
assert(this->n != 0);
}
mpz_class::~mpz_class() {
delete [] this->b;
this->b = 0;
this->n = 0;
}
mpz_class &mpz_class::operator=(mpz_class ob) {
this->n = ob.n;
if (ob.n == 0) {
delete [] this->b;
this->b = 0;
} else {
delete [] this->b;
this->b = new int[ob.n];
for (int i = 0; i < ob.n; i++) {
this->b[i] = ob.b[i];
}
}
return *this;
}
bool operator==(mpz_class const &a, mpz_class const &b) {
int i, less;
bool isEqual = true;
if (a.n < b.n) {
less = a.n;
} else {
less = b.n;
}
for (i = 0; i < less; i++) {
if ((a.b[i]) != (b.b[i])) {
isEqual = false;
}
}
if (a.n < b.n) {
for (; i < b.n; i++)
if (b.b[i] != 0) {
isEqual = false;
}
} else {
for (;i < a.n; i++)
if (a.b[i] != 0) {
isEqual = false;
}
}
return isEqual;
}
mpz_class operator+(mpz_class const &a, mpz_class const &b) {
mpz_class r;
mpz_class const * more_ab;
int less_n;
if (a.n > b.n) {
r.n = a.n;
more_ab = &a;
less_n = b.n;
} else {
r.n = b.n;
more_ab = &b;
less_n = a.n;
}
r.b = new int [r.n];
int i, carry = 0;
for (i = 0; i < less_n; i++) {
int s = a.b[i] + b.b[i] + carry;
if (s >= CMASK) {
carry = 1;
r.b[i] = (s & BMASK);
} else {
carry = 0;
r.b[i] = s; /* need */
}
}
for (;i < r.n; i++) {
int s = more_ab->b[i] + carry;
if (s >= CMASK) {
carry = 1;
r.b[i] = (s & BMASK); /* need */
} else {
carry = 0;
r.b[i] = (s & BMASK); /* need */ /* not to insert break keyword.*/
}
}
if (carry) {
int *new_body = new int [r.n + 1];
for (i = 0; i < r.n; i++)
new_body[i] = r.b[i];
new_body[i] = carry;
delete [] r.b;
r.b = new_body;
r.b[r.n] = 1; /* need */
r.n++;
}
return r;
}
mpz_class sub(mpz_class const &a, mpz_class const &b) {
int vCount, moreCount, i;
int diff;
int borrowR = 0;
bool flagMore, flagLess;
mpz_class r;
flagMore = false;
flagLess = false;
moreCount = a.n;
vCount = a.n;
r = a;
if (a.n > b.n) {
flagMore = true;
vCount = b.n;
moreCount = a.n;
r = a;
}
if (a.n < b.n) {
flagLess = true;
vCount = a.n;
moreCount = b.n;
r = b;
}
borrowR = 0;
for (i = 0; i < vCount; i++) {
diff = a.b[i] - b.b[i] - borrowR;
if (diff < 0) {
borrowR = 1;
r.b[i] = diff + CMASK;
} else {
borrowR = 0;
r.b[i] = diff;
}
}
if (flagMore) {
for (;i < moreCount; i++) {
diff = a.b[i] - borrowR;
if (diff < 0) {
borrowR = 1;
r.b[i] = diff + CMASK;
} else {
borrowR = 0;
r.b[i] = diff;
}
}
}
if (flagLess) {
for (;i < moreCount; i++) {
if (b.b[i] > 0) {
borrowR = 1;
}
}
}
if (borrowR > 0) throw std::underflow_error("negative value.");
return r;
}
mpz_class mul2(mpz_class const &a, mpz_class const &b) {
mpz_class Rshift = b;
mpz_class Lshift = a;
mpz_class r = 0;
int lsb;
while (!mpz_class::iszero(Rshift)) {
mpz_class::RightShift(Rshift, lsb);
if (lsb) {
r = r + Lshift;
}
mpz_class::LeftShift(Lshift);
}
return r;
}
void mpz_class::LeftShift(mpz_class &a) {
int i, msb;
msb = 0;
for (i = 0; i < a.n; i++) {
a.b[i] *= 2;
if (msb > 0)
a.b[i] = (a.b[i] | 0x01);
if (a.b[i] > BMASK) {
msb = 1;
a.b[i] -= CMASK;
} else {
msb = 0;
}
}
if (msb > 0) {
int *newbody;
newbody = new int [a.n + 1];
newbody[a.n] = 1;
for (int i = 0; i < a.n; i++) {
newbody[i] = a.b[i];
}
a.n++;
delete a.b;
a.b = newbody;
}
}
void mpz_class::RightShift(mpz_class &a, int &lsb_out) {
int i, lsb;
lsb = 0;
for (i = a.n - 1; i >= 0; --i) {
if (lsb > 0)
a.b[i] = (a.b[i] | CMASK);
if ((a.b[i] & 0x01) > 0)
lsb = 1;
else
lsb = 0;
a.b[i] /= 2;
}
lsb_out = lsb;
if (a.b[a.n - 1] == 0) {
int *newbody;
newbody = new int [a.n - 1];
for (int i = 0; i < a.n - 1; i++)
newbody[i] = a.b[i];
a.n--;
delete a.b;
a.b = newbody;
}
}
void mpz_class::LeftShift2(int &msb, mpz_class &a) {
int i, msb_v;
msb_v = 0;
for (i = 0; i < a.n; i++) {
a.b[i] *= 2;
if (msb_v > 0)
a.b[i] = (a.b[i] | 0x01);
if (a.b[i] > BMASK) {
msb_v = 1;
a.b[i] -= CMASK;
} else {
msb_v = 0;
}
}
msb = msb_v;
}
void mpz_class::LeftShift3(mpz_class &a, int msb) {
int i, msb_v;
msb_v = msb;
for (i = 0; i < a.n; i++) {
a.b[i] *= 2;
if (msb_v > 0)
a.b[i] = (a.b[i] | 0x01);
if (a.b[i] > BMASK) {
msb_v = 1;
a.b[i] -= CMASK;
} else {
msb_v = 0;
}
}
if (msb_v > 0) {
int *newbody;
newbody = new int [a.n + 1];
newbody[a.n] = 1;
for (int i = 0; i < a.n; i++) {
newbody[i] = a.b[i];
}
a.n++;
delete a.b;
a.b = newbody;
}
}
void div2(mpz_class const &a, mpz_class const &b, mpz_class &q, mpz_class &r) {
if (b == mpz_class(0)) {
std::cout << "null devided." << std::endl;
return;
}
/* LeftRest <- LeftShiftBuff */
mpz_class LeftRest(0);
mpz_class LeftShiftBuff = a;
mpz_class Quotient(0);
int msb, lsb;
msb = 0;
int n = a.n * BIT;
while (n > 0) {
// std::cout << "LeftShiftBuff=" << LeftShiftBuff << std::endl;
// std::cout << "LeftRest=" << LeftRest << std::endl;
mpz_class::LeftShift2(msb, LeftShiftBuff);
mpz_class::LeftShift3(LeftRest, msb);
lsb = 0;
if (b <= LeftRest) {
LeftRest = LeftRest - b;
lsb = 1;
}
mpz_class::LeftShift3(Quotient, lsb);
// std::cout << "Quotient=" << Quotient << std::endl;
n--;
}
q = Quotient;
r = LeftRest;
}
bool operator<(mpz_class const &a, mpz_class const &b) {
try {
sub(a, b);
} catch (std::underflow_error &e) {
return true;
}
return false;
}
bool mpz_class::iszero(mpz_class &n) {
bool isZero = true;
for (int i = 0; i < n.n; i++)
if (n.b[i] != 0) {
isZero = false;
break;
}
return isZero;
}
std::ostream &operator<<(std::ostream &stream, mpz_class c) {
std::basic_string<char> mod10;
mpz_class q, n;
int mod;
bool fzero;
fzero = true;
n = c;
for(;;) {
/* div10(n, q, mod); */
{
q = n;
mod = 0;
for (int i = 0; i < n.n * BIT; i++) {
/* shift_div(mod, q); */
{
int cy, i;
cy = 0;
for (i = 0; i < n.n; i++) {
q.b[i] = q.b[i] << 1;
if (cy)
q.b[i] = q.b[i] | 0x01;
cy = (q.b[i] >> BIT);
q.b[i] = q.b[i] & BMASK;
}
mod = mod << 1;
if (cy)
mod = mod | 0x01;
}
if (mod >= 10) {
q.b[0] = q.b[0] | 0x01;
mod = mod - 10;
}
}
}
if (mpz_class::iszero(q) && mod == 0)
break;
mod10 = (char)('0' + mod) + mod10;
fzero = false;
n = q;
}
if (fzero)
stream << '0';
else
stream << mod10;
return stream;
}
} /* namespace QZ */
int main() {
QZ::mpz_class s;
QZ::mpz_class t;
QZ::mpz_class const1;
int prec = 16;
const1 = 1;
for (int n = 0; n < prec; n++)
const1 *= 2; /* const1 << prec */
s = const1;
int n;
for (n = 2; ; n++) {
t = const1 / n;
if (t == 0) break;
if (n % 2 == 0)
s -= t;
else
s += t;
}
std::cout << "n = " << n << std::endl;
s.QZ::mpz_class::print_tmp1(prec);
return 0;
}
/* end */