C++高精度模板

#include <vector>
#include <string>
#include <iostream>
#include <string.h>
#include <stdio.h>

#define abs(a) ((a)>=0?(a):-(a))
 
using namespace std;
 
class LargeInteger
{
public:
 
    LargeInteger(const char * s);
 
    LargeInteger(unsigned long long a = 0):negative(false)
    {
        if( a == 0 ) 
        {
            v.resize(1);
            n = 0;
            return ;
        }
 
        while(a)
        {
            v.push_back(a%base);
            a /= base;
        }
        n = v.size();
    }
 
    LargeInteger(long long a)
    {
        bool t = (a<0);
        *this = (unsigned long long) abs(a);
        negative = t;
    }
 
    LargeInteger(int a)
    {
        *this = (long long) a;
    }
 
    LargeInteger(short a)
    {
        *this = (long long) a;
    }
 
    LargeInteger(char a)
    {
        *this = (long long) a;
    }
 
    LargeInteger(unsigned int a)
    {
        *this = (unsigned long long)a;
    }
 
    LargeInteger(unsigned short a)
    {
        *this = (unsigned long long)a;
    }
 
    LargeInteger(unsigned char a)
    {
        *this = (unsigned long long)a;
    }
 
    LargeInteger operator + (const LargeInteger &other) const
    {
        LargeInteger ret;
        add(this , &other , &ret);
        return ret;
    }
 
    LargeInteger &operator +=(const LargeInteger &other)
    {
        add(this , &other , this);
        return *this;
    }
 
    LargeInteger operator - (const LargeInteger &other) const
    {
        LargeInteger ret;
        sub(this , &other , &ret);
        return ret;
    }
 
    LargeInteger &operator -=(const LargeInteger &other)
    {
        sub(this ,  &other , this);
        return *this;
    }
 
    LargeInteger operator * (const LargeInteger &other) const
    {
        LargeInteger ret;
        mul(this , &other , &ret);
        return ret;
    }
 
    LargeInteger &operator *=(const LargeInteger &other)
    {
        mul(this ,  &other , this);
        return *this;
    }
 
    LargeInteger operator / (const LargeInteger &other) const
    {
        LargeInteger ret;
        div(this , &other , &ret , NULL);
        return ret;
    }
 
    LargeInteger &operator /= (const LargeInteger &other)
    {
        div(this , &other , this , NULL);
        return *this;
    }
 
    LargeInteger operator % (const LargeInteger &other) const
    {
        LargeInteger ret;
        div(this , &other , NULL , &ret);
        return ret;
    }
 
    LargeInteger &operator %= (const LargeInteger &other)
    {
        div(this , &other , NULL , this);
        return *this;
    }
 
    LargeInteger operator ^(unsigned long long p)
    {
        LargeInteger ret = 1;
        for(LargeInteger t = *this ; p ; p >>= 1)
        {
            if(p & 1) ret *= t;
            t *= t;
        }
        return ret;
    }
 
    bool operator < (const LargeInteger &other) const
    {
        return compare(*this , other) < 0;
    }
 
    bool operator > (const LargeInteger &other) const
    {
        return compare(*this , other) > 0;
    }
 
    bool operator == (const LargeInteger &other) const
    {
        return compare(*this , other) == 0;
    }
 
    bool operator <= (const LargeInteger &other) const
    {
        return compare(*this , other) <= 0;
    }
 
    bool operator >= (const LargeInteger &other) const
    {
        return compare(*this , other) >= 0;
    }
 
    bool operator != (const LargeInteger &other) const
    {
        return compare(*this , other) != 0;
    }
 
    LargeInteger operator -() const
    {
        LargeInteger ret = *this;
        ret.negative = !ret.negative;
        return ret;
    }
 
    LargeInteger operator +() const
    {
        return *this;
    }
 
    LargeInteger absolute() const
    {
        LargeInteger ret = *this;
        ret.negative = false;
        return ret;
    }
 
    string ToString();
 
    static void add(const LargeInteger *pa ,const LargeInteger *pb, LargeInteger *pc);
    static void sub(const LargeInteger *pa ,const LargeInteger *pb, LargeInteger *pc);
    static void mul(const LargeInteger *pa ,const LargeInteger *pb, LargeInteger *pc);
    static void div(const LargeInteger *pa ,const LargeInteger *pb ,LargeInteger *pc , LargeInteger *pd);
 
private:
    static int compare(const int *pa , int an , const int *pb , int bn);
    static int compare(const LargeInteger &a , const LargeInteger &b);
 
    static void add(const int *pa , int an , const int *pb , int bn ,int *pc , int &cn);
    static bool sub(const int *pa , int an , const int *pb , int bn ,int *pc , int &cn);
    static void mul(const int *pa , int an , const int *pb , int bn ,int *pc , int &cn);
    static void div(      int *pa , int &an, const int *pb , int bn, int *pc , int &cn); //a既是输入被除数也是余数
 
    static void mul(const int *pa , int an ,long long b, int *c , int &cn);
    static int div(const int *pa,const int an,const int *pb,const int bn);
 
    static int ValueToStr(int val, char *s,int n)
    {
        int ret = 0;
        s[n] = 0;
        for(int i = n - 1; i >= 0 ; i--)
        {
            s[i] = (val % 10) + '0';
            val /= 10;
            if(val == 0 && ret == 0) ret = i;
        }
        return ret;
    }
 
    static int StrToValue(const char *s,int n)
    {
        int ret = 0;
        for(int i = 0; i < n; i++)
        {
            ret *= 10;
            ret += s[i] - '0';
        }
        return ret;
    }
 
    vector<int> v;
    int n;
    bool negative;
    static const int base;
};
 
const int LargeInteger::base = 1000000000;
 
LargeInteger::LargeInteger(const char * s)
{
    if( *s == '-' || *s == '+') negative = ( *s++ == '-');
    else negative = false;
 
    while( *s && *s == '0' ) s++;
 
    if( !*s ) { *this = 0; return; }
 
    int len = strlen(s) , i;
    for( i = len - 9; i >= 0 ; i -= 9) v.push_back(StrToValue(s+i,9));
 
    if( (i += 9) > 0) v.push_back(StrToValue(s,i));
 
    n = v.size();
}
 
string LargeInteger::ToString()
{
    if( n == 0 ) return "0";
 
    char s[10];
    int *p = &v[0];
    string ret;
 
    if(negative) ret += '-';
 
    ret += (s + ValueToStr( p[n-1] , s , 9));
 
    for(int i = n - 2; i >= 0; i--)
    {
        ValueToStr(p[i] , s , 9);
        ret += s;
    }
 
    return ret;
}
 
int LargeInteger::compare(const int *pa , int an , const int *pb , int bn )
{
    if( an == bn )
    {
        for(int i=an-1 ; i >= 0 ; i--)
        {
            if(pa[i] != pb[i]) return pa[i] - pb[i];
        }
        return 0;
    }
    return an - bn;
}
 
int LargeInteger::compare(const LargeInteger &a , const LargeInteger &b)
{
    if( a.negative != b.negative)
    {
        return b.negative - a.negative;
    }
    return b.negative ? -compare( &a.v[0], a.n, &b.v[0], b.n) : compare( &a.v[0], a.n, &b.v[0], b.n);
}
 
void LargeInteger::add(const LargeInteger *pa ,const LargeInteger *pb, LargeInteger *pc)
{
    pc->v.resize( max(pa->n,pb->n) + 1);
 
    if( pa->negative == pb->negative )
    {
        pc->negative = pa->negative;
        add(&pa->v[0] ,pa->n , &pb->v[0] , pb->n , &pc->v[0] , pc->n);
    }
    else
    {
        pc->negative = sub(&pa->v[0] ,pa->n , &pb->v[0] , pb->n , &pc->v[0] , pc->n) ? \
            !pa->negative : pa->negative;
 
        if(pc->n == 0) pc->negative = false;
    }
}
 
void LargeInteger::sub(const LargeInteger *pa ,const LargeInteger *pb, LargeInteger *pc)
{
    pc->v.resize( max(pa->n,pb->n) + 1);
 
    if( pa->negative == pb->negative )
    {   
        pc->negative = sub(&pa->v[0] ,pa->n , &pb->v[0] , pb->n , &pc->v[0] , pc->n) ? \
            !pa->negative : pa->negative;
 
        if(pc->n == 0) pc->negative = 0;
    }
    else
    {
        pc->negative = pa->negative;
        add(&pa->v[0] ,pa->n , &pb->v[0] , pb->n , &pc->v[0] , pc->n);
    }
}
 
void LargeInteger::mul(const LargeInteger *pa ,const LargeInteger *pb, LargeInteger *pc)
{
    pc->negative = (pa->negative != pb->negative);
 
    if( pa->n == 0 || pb->n == 0)
    {
        *pc = 0;
        return ;
    }
 
    pc->v.resize(pa->n+pb->n);
    mul(&pa->v[0] , pa->n , &pb->v[0] , pb->n , &pc->v[0] , pc->n);
}
 
void LargeInteger::div(const LargeInteger *pa ,const LargeInteger *pb ,LargeInteger *pc , LargeInteger *pd)
{
    LargeInteger td = *pa;
    LargeInteger tc;
    if( pb->n == 0 )
        throw "Divided by 0";
    tc.negative = (pa->negative != pb->negative);
    tc.v.resize(pa->n,0);
    div(&td.v[0], td.n , &pb->v[0], pb->n , &tc.v[0], tc.n);
    if( tc.n == 0 ) tc.negative = false;
    if( td.n == 0 ) td.negative = false;
    if(pc) *pc = tc;
    if(pd) *pd = td;
}
 
 
void LargeInteger::add(const int *pa , int an , const int *pb , int bn ,int *pc , int &cn)
{
    int t = 0 , i;
 
    if( an < bn )
    {
        swap(pa,pb);
        swap(an,bn);
    }
 
    for( i = 0; i < bn ; i++)
    {
        t = pa[i] + pb[i] + (t>=base);
        pc[i] = (t>=base) ? t - base : t;
    }
 
    for( ; i < an ; i++)
    {
        t = pa[i] + (t>=base);
        pc[i] = (t>=base) ? t - base : t; 
    }
 
    if(t>=base) pc[i++] = 1;
    cn = i;
}
 
bool LargeInteger::sub(const int *pa , int an , const int *pb , int bn ,int *pc ,int &cn)
{
    int t = 0 ,i;
    bool swaped = false;
 
    if(compare(pa,an,pb,bn) < 0)
    {
        swaped = true;
        swap(pa,pb);
        swap(an,bn);
    }
 
    for(i = 0 ; i < bn ; i++)
    {
        t = pa[i] - pb[i] - (t<0);
        pc[i] = (t<0) ? t + base : t;
    }
 
    for( ; i < an; i++)
    {
        t = pa[i] - (t<0);
        pc[i] = (t<0) ? t + base : t;
    }
 
    while( --i >= 0 && pc[i] == 0 );
    cn = i + 1; 
 
    return swaped;
}
 
void LargeInteger::mul(const int *pa , int an ,long long b, int *c ,int &cn)
{
    cn = 0;
    if( b == 0 ) return;
    long long t = 0;
    for( ; cn < an ; cn++)
    {
        t = b * pa[cn] + t / base;
        c[cn] = (t % base);
    }
    if(t/=base) c[cn++] = t;
}
 
 
void LargeInteger::mul(const int *pa , int an , const int *pb , int bn ,int *pc ,int &cn)
{
    int *pSum = new int[an+bn];
    int *pProduct = new int[an+bn];
    int nProduct;
    cn = 0;
    memset(pSum,0,sizeof(int)*(an+bn));
    for(int i = 0; i < bn; i++)
    {
        mul(pa,an,pb[i],pProduct+i,nProduct);
        add(pProduct,nProduct+i,pSum,cn,pSum,cn);
        pProduct[i] = 0;
    }
 
    memcpy(pc,pSum,cn*sizeof(int));
    delete []pSum;
    delete []pProduct;
}
 
int LargeInteger::div(const int *pa,const int an,const int *pb,const int bn)
{
    int *pc = new int[bn+1];
    int cn;
 
    long long s = 0 , e = base , m;
    while( s + 1 < e )
    {
        m = (s + e) >> 1;
        mul(pb,bn,m,pc,cn);
 
        if(compare(pc,cn,pa,an) > 0) e = m;
        else s = m;
    }
 
    delete []pc;
    return s;
}
 
void LargeInteger::div(int *pa , int &an, const int *pb , int bn, int *pc , int &cn)
{
    int t;
    int *pt = new int[an+1];
    int *pfa = pa + an - bn;
    int tn, fan = bn;
 
    memset(pc,0,sizeof(int)*an);
    while( pfa >= pa )
    {
        t = div(pfa , fan , pb , bn);
        pc[pfa-pa] = t;
        mul(pb,bn,t,pt,tn);
        sub(pfa,fan,pt,tn,pfa,fan);
 
        if( bn != fan )
        {
            pfa -= (bn - fan); 
            fan = bn;
        }
        else
        {
            pfa--;
            fan++;
        }
    }
 
    cn = an - bn + 1;
    if( cn < 0 ) cn = 0;
    if( cn - 1 >= 0 && pc[cn-1] == 0) cn--;
 
    while( --an >=0 && pa[an] == 0);
    an++;
 
    delete []pt;
}
 
 
////////////////////////////////////////////////////////////////////////////////////////////////

//POJ 2109 Power of Cryptography
//不知道为什么POJ abs()编译不过去,说math.h 和 stdio.h 中重定义了,所以去掉了头文件


int main()
{
    int n,len;
    char str[105];
    while(scanf("%d%s",&n,str)!=EOF)
    {
        LargeInteger p(str);
        LargeInteger s = 0 ,e = p , m; 

        while(s + 1 < e)
        {
            m = (s + e) / 2;
            if( (m^n) > p ) e = m;
            else s = m;
        }

        cout<<s.ToString()<<endl;
    }

    return 0;
}

 

posted on 2013-09-21 22:42  十指之间  阅读(413)  评论(0编辑  收藏  举报

导航