const int maxl = 25;
const int bitlen = 4;
char buffer[maxl * bitlen + 10];
const int MAXL = 10000;
LL tmp[bitlen * maxl];
LL q[bitlen * maxl];
struct Bignum
{
int a[maxl];
int sz;
bool read()
{
memset(a, 0, sizeof(a));
sz = 0;
if (scanf("%s", buffer) != 1) return false;
int n = strlen(buffer);
int i;
for (i = n - 1; i >= 0; i -= bitlen)
{
LL x = 0, y = 1;
for (int j = i; j > i - bitlen && j >= 0; --j)
{
x += y*(buffer[j] - '0');
y *= 10;
}
a[sz++] = x;
}
return true;
}
Bignum()
{
memset(a, 0, sizeof(a));
sz = 0;
}
Bignum(LL x)
{
memset(a, 0, sizeof(a));
sz = 0;
if (x == 0) sz = 1;
while (x != 0)
{
a[sz++] = x % MAXL;
x /= MAXL;
}
}
Bignum(const Bignum&bg)
{
sz = bg.sz;
memset(a, 0, sizeof(a));
for (int i = 0; i < sz; ++i) a[i] = bg.a[i];
}
int cmp(const Bignum&bg) const
{
if (sz>bg.sz) return 1;
else if (sz < bg.sz) return -1;
for (int i = sz-1; i >= 0; --i)
if (a[i] < bg.a[i]) return -1;
else if (a[i]>bg.a[i]) return 1;
return 0;
}
bool operator<(const Bignum&bg) const { return cmp(bg) < 0; }
bool operator==(const Bignum&bg) const { return cmp(bg) == 0; }
bool operator<=(const Bignum&bg) const { return cmp(bg) <= 0; }
bool operator>(const Bignum&bg) const { return cmp(bg)>0; }
bool operator>=(const Bignum&bg) const { return cmp(bg) >= 0; }
bool operator!=(const Bignum&bg) const { return cmp(bg) != 0; }
Bignum operator=(const Bignum&bg)
{
sz = bg.sz;
memset(a, 0, sizeof(a));
for (int i = 0; i < sz; ++i) a[i] = bg.a[i];
return *this;
}
void add(const Bignum&bg)
{
sz = max(sz, bg.sz);
for (int i = 0; i < sz; ++i)
{
a[i] += bg.a[i];
a[i + 1] += a[i] / MAXL;
a[i] %= MAXL;
}
while (a[sz] != 0) ++sz;
}
Bignum operator+(const Bignum&bg)
{
if (bg == 0) return *this;
Bignum ret = *this;
ret.add(bg);
return ret;
}
void sub(const Bignum&small)
{
for (int i = 0; i < sz; ++i)
{
a[i] -= small.a[i];
if (a[i] < 0)
{
int j = i + 1;
a[i] += MAXL;
while (--a[j]<0)
{
a[j] += MAXL;
++j;
}
}
}
while (sz>1 && a[sz - 1] == 0) --sz;
}
void mul(const Bignum&b)
{
memset(tmp,0,sizeof(tmp));
for(int i=0;i<sz;++i) {
for(int j=0;j<b.sz;++j) {
tmp[i+j]+=a[i]*b.a[j];
tmp[i+j+1]+=tmp[i+j]/MAXL;
tmp[i+j]%=MAXL;
}
}
sz+=b.sz;
while(tmp[sz]>0) {
tmp[sz+1]+=tmp[sz]/MAXL;
tmp[sz]%=MAXL;
++sz;
}
while(sz>1&&tmp[sz-1]==0) --sz;
for(int i=0;i<sz;++i) a[i]=tmp[i];
}
Bignum operator-(const Bignum&small)
{
if (small == 0) return *this;
int cp = cmp(small);
if (cp == 0) return 0;
Bignum A = *this, B = small;
A.sub(B);
return A;
}
Bignum operator/(LL x)
{
Bignum ret = *this;
LL y = 0;
for (int i = sz - 1; i >= 0; --i)
{
y = y*MAXL + ret.a[i];
ret.a[i] = y / x, y %= x;
}
while (ret.sz > 1 && ret.a[ret.sz - 1] == 0) --ret.sz;
return ret;
}
LL operator%(LL x)
{
LL y = 0;
for (int i = sz - 1; i >= 0; --i)
{
y = y*MAXL + a[i];
if (y >= x) y %= x;
}
return y;
}
Bignum operator*(const Bignum&bg)
{
Bignum ret=*this;
ret.mul(bg);
return ret;
}
Bignum pow(LL x)
{
Bignum ret = 1, base = *this;
while (x)
{
if (x & 1) ret = ret*base;
base = base*base;
x >>= 1;
}
return ret;
}
Bignum operator*(LL x)
{
return *this*Bignum(x);
}
bool Try_sub(char *s,char *t,int lent,int lens)
{
if(lent>lens) return false;
for(int i=0;i<lens;++i) q[i]=s[i];
bool ok=true;
for(int i=0;i<lens;++i) {
s[i]-=t[i];
if(s[i]>=0) continue;
int j=i+1;
s[i] += 10;
while (j<lens && --s[j]<0)
{
s[j] += 10;
++j;
}
if(j>=lens) { ok=false; break; }
}
if(ok) return true;
for(int i=0;i<lens;++i) s[i]=q[i];
return false;
}
Bignum operator/(const Bignum&bg)
{
int cp=cmp(bg);
if(cp==0) return 1;
else if(cp<0) return 0;
char * s= new char[bitlen*sz+5], *t=new char [bitlen*sz+5];
char * ans= new char [bitlen*sz+5];
int lens=0,lent=0;
s[lens]=t[lent]=0;
for(int i=0;i<sz;++i) {
int x=a[i];
for(int j=0;j<4;++j) {
s[lens++]=x%10;
s[lens]=0;
x/=10;
}
x=bg.a[i];
for(int j=0;j<4;++j) {
t[lent++]=x%10;
t[lent]=0;
x/=10;
}
}
while(lent>1 && t[lent-1]==0) --lent;
while(lens>1 && s[lens-1]==0) --lens;
for(int i=lent;i<lens;++i) t[i]=0;
for(int i=lens-1;i>=0;--i) {
ans[i]=0;
while(Try_sub(s+i,t,lent,lens-i)) ++ans[i];
}
for(int i=lens;i<=lens+4;++i) ans[i]=0;
Bignum ret;
for(int i=0;i<lens;i+=4) {
ret.a[i/4]=1000*ans[i+3]+100*ans[i+2]+10*ans[i+1]+ans[i];
}
ret.sz=sz;
while(ret.sz>1 && ret.a[ret.sz-1]==0) --ret.sz;
delete [] s; delete [] t; delete [] ans;
return ret;
}
Bignum operator%(const Bignum&bg)
{
if (bg == 0) return 0;
Bignum ret = *this;
ret = (ret / bg)*bg;
return *this - ret;
}
void output() const
{
printf("%d", a[sz - 1]);
for (int i = sz - 2; i >= 0; --i) printf("%04d", a[i]);
printf("\n");
}
};
第二版:压9位的大数
typedef long long LL;
const int maxl = 50;
const int bitlen = 9;
char buffer[maxl * bitlen + 10];
const int MAXL = 1000000000; //10^9
LL tmp[bitlen * maxl];
LL q[bitlen * maxl];
typedef unsigned long long u_long;
struct Bignum
{
int a[maxl];
int sz;
bool read();
Bignum() { memset(a, 0, sizeof(a)); sz = 1; }
Bignum(u_long x);
Bignum(const Bignum&);
int cmp(const Bignum&bg) const;
bool operator<(const Bignum&bg) const { return cmp(bg) < 0; }
bool operator==(const Bignum&bg) const { return cmp(bg) == 0; }
bool operator<=(const Bignum&bg) const { return cmp(bg) <= 0; }
bool operator>(const Bignum&bg) const { return cmp(bg)>0; }
bool operator>=(const Bignum&bg) const { return cmp(bg) >= 0; }
bool operator!=(const Bignum&bg) const { return cmp(bg) != 0; }
bool Try_sub(char *s,char *t,int lent,int lens);
Bignum& operator = (const Bignum&bg);
Bignum& operator += (const Bignum&bg);
Bignum & operator -= (const Bignum& bg);
Bignum& operator *= (const Bignum& bg);
Bignum& operator /= (const Bignum& bg);
Bignum& operator /= (int x);
int operator % (int x);
Bignum operator + (const Bignum&bg) const { return Bignum(*this) += bg; }
Bignum operator / (const Bignum& bg) const { return Bignum(*this) /= bg; }
Bignum operator * (const Bignum& bg) const { return Bignum(*this) *= bg; }
Bignum operator - (const Bignum&bg) const { return Bignum(*this) -= bg; }
Bignum operator%(const Bignum&bg) const { return *this - *this / bg * bg; }
Bignum operator / (int x) const { return Bignum(*this) /= x; }
Bignum pow(LL x);
void output() const
{
printf("%d", a[sz - 1]);
for (int i = sz - 2; i >= 0; --i) printf("%09d", a[i]);
printf("\r");
}
};
bool Bignum::read()
{
memset(a, 0, sizeof(a));
sz = 0;
if (scanf("%s", buffer) != 1) return false;
int n = strlen(buffer);
int i;
for (i = n - 1; i >= 0; i -= bitlen)
{
u_long x = 0, y = 1;
for (int j = i; j > i - bitlen && j >= 0; --j)
{
x += y * (buffer[j] - '0');
y *= 10;
}
a[sz++] = x;
}
return true;
}
Bignum::Bignum(u_long x)
{
memset(a, 0, sizeof(a));
sz = 0;
if (x == 0) sz = 1;
while (x != 0)
{
a[sz++] = x % MAXL;
x /= MAXL;
}
}
Bignum::Bignum(const Bignum& bg)
{
sz = bg.sz;
memcpy(a,bg.a,sizeof(a));
}
int Bignum::cmp(const Bignum&bg) const
{
if (sz>bg.sz) return 1;
else if (sz < bg.sz) return -1;
for (int i = sz-1; i >= 0; --i)
if (a[i] < bg.a[i]) return -1;
else if (a[i] > bg.a[i]) return 1;
return 0;
}
Bignum& Bignum::operator=(const Bignum& bg)
{
sz = bg.sz;
memcpy(a,bg.a,sizeof(a));
return *this;
}
Bignum& Bignum::operator += (const Bignum& bg)
{
sz = max(sz, bg.sz);
for (int i = 0; i < sz; ++i)
{
a[i] += bg.a[i];
a[i + 1] += a[i] / MAXL;
a[i] %= MAXL;
}
while (a[sz] != 0) ++sz;
return *this;
}
Bignum& Bignum::operator -= (const Bignum& bg)
{
for (int i = 0; i < sz; ++i)
{
a[i] -= bg.a[i];
if (a[i] < 0)
{
int j = i + 1;
a[i] += MAXL;
while (--a[j]<0)
{
a[j] += MAXL;
++j;
}
}
}
while (sz>1 && a[sz - 1] == 0) --sz;
return *this;
}
Bignum& Bignum::operator*=(const Bignum& b)
{
memset(tmp,0,sizeof(tmp));
u_long w = 0;
for(int i=0;i<sz;++i) if (a[i]) {
for(int j=0;j<b.sz;++j) if (b.a[j]) {
int k = i + j;
w = (u_long) a[i] * b.a[j];
while (w > 0) {
w += tmp[k];
tmp[k++] = w % MAXL;
w /= MAXL;
}
}
}
sz+=b.sz;
w = 0;
while(tmp[sz]>0) {
w += (u_long) tmp[sz];
tmp[sz] = w % MAXL;
w /= MAXL;
++sz;
}
while(sz>1&&tmp[sz-1]==0) --sz;
for(int i=0;i<sz;++i) a[i] = tmp[i];
return *this;
}
Bignum& Bignum::operator /= (int x)
{
u_long y = 0;
for (int i = sz - 1; i >= 0; --i)
{
y = y * MAXL + a[i];
a[i] = y / x, y %= x;
}
while (sz > 1 && a[sz - 1] == 0) --sz;
return *this;
}
int Bignum::operator % (int x)
{
u_long y = 0;
for (int i = sz - 1; i >= 0; --i)
{
y = y*MAXL + a[i];
if (y >= x) y %= x;
}
return y;
}
Bignum Bignum::pow(LL x)
{
Bignum ret = 1, base = *this;
while (x)
{
if (x & 1) ret = ret * base;
base = base * base;
x >>= 1;
}
return ret;
}
bool Bignum::Try_sub(char * s,char * t,int lent,int lens)
{
if(lent>lens) return false;
for(int i=0;i<lens;++i) q[i]=s[i];
bool ok=true;
for(int i=0;i<lens;++i) {
s[i]-=t[i];
if(s[i]>=0) continue;
int j=i+1;
s[i] += 10;
while (j<lens && --s[j]<0)
{
s[j] += 10;
++j;
}
if(j>=lens) { ok=false; break; }
}
if(ok) return true;
for(int i=0;i<lens;++i) s[i]=q[i];
return false;
}
Bignum& Bignum::operator /= (const Bignum& bg)
{
int cp=cmp(bg);
if(cp==0) return *this = 1;
else if(cp<0) return *this = 0;
char * s= new char[bitlen*(sz+2)], *t=new char [bitlen*(sz+2)];
char * ans= new char [bitlen*(sz+2)];
int lens=0,lent=0;
s[lens]=t[lent]=0;
for(int i=0;i<sz;++i) {
int x=a[i];
for(int j=0;j<bitlen;++j) {
s[lens++]=x%10;
s[lens]=0;
x/=10;
}
x=bg.a[i];
for(int j=0;j<bitlen;++j) {
t[lent++]=x%10;
t[lent]=0;
x/=10;
}
}
while(lent>1 && t[lent-1]==0) --lent;
while(lens>1 && s[lens-1]==0) --lens;
for(int i=lent;i<lens;++i) t[i]=0;
for(int i=lens-1;i>=0;--i) {
ans[i]=0;
while(Try_sub(s+i,t,lent,lens-i)) ++ans[i];
}
for(int i=lens;i<=lens+bitlen;++i) ans[i]=0;
for(int i=0;i<lens;i+=bitlen) {
u_long x = 1;
a[i/bitlen] = 0;
for(int j = 0; j < bitlen; ++j) {
a[i/bitlen] += x * ans[j+i];
x *= 10;
}
}
while(sz>1 && a[sz-1]==0) --sz;
delete [] s; delete [] t; delete [] ans;
return *this;
}