Which is a good C++ BigInteger class for programming contests?

前端 未结 1 1315
隐瞒了意图╮
隐瞒了意图╮ 2021-01-20 13:27

I was just wondering which will the best BigInteger class in C++ for programming contests which do not allow external libraries?

Mainly I was looking for a class whi

1条回答
  •  无人及你
    2021-01-20 13:39

    So far I've only needed unsigned integer big numbers for codechef, but codechef only gives 2KB, so I don't have the full implementation up there anywhere, just the members needed for that problem. My code also assumes that long long has at least twice as many bits as a unsigned, though that's pretty safe. The only real trick to it is that different biguint classes may have different data lengths. Here's summaries of the more interesting functions.

    #define BIG_LEN()  (data.size()>rhs.data.size()?data.size():rhs.data.size())
        //the length of data or rhs.data, whichever is bigger
    #define SML_LEN()  (data.size() rhs.length
           add(carry, SML_LEN())
    biguint& operator*=(const biguint& rhs) 
        biguint lhs = *this;
        resize data to data.length + rhs.length
        zero out data
        for each element j in lhs
            long long t = lhs[j]
            for each element i in rhs (and j+i>uint_bits, k+1);
    //note this was public, so I could do both at the same time when needed
    //operator /= and %= both just call this
    //I have never needed to divide by a biguint yet.
    biguint& div(unsigned int rhs, unsigned int & mod) 
        long long carry = 0
        for each element i from data length to zero
            carry = (carry << uint_bits) | data[i]
            data[i] = carry/rhs;
            carry %= rhs
        mod = carry
    //I have never needed to shift by a biguint yet
    biguint& operator<<=(unsigned int rhs) 
        resize to have enough room, always at least 1 bigger
        const unsigned int bigshift = rhs/uint_bits;
        const unsigned int lilshift = rhs%uint_bits;
        const unsigned int carry_shift = (uint_bits-lilshift)%32;
        for each element i from bigshift to zero
             t = data[i-bigshift] << lilshift;
             t |= data[i-bigshift-1] >> carry_shift;
             data[i] = t;
        if bigshift < data.size
            data[bigshift] = data[0] << lilshift
        zero each element i from 0 to bigshift
    std::ofstream& operator<<(std::ofstream& out, biguint num)
        unsigned int mod
        vector reverse
        do 
            num.div(10,mod);
            push back mod onto reverse
        while num greater than 0
        print out elements of reverse in reverse
    std::ifstream& operator>>(std::ifstream& in, biguint num)
        char next
        do
            in.get(next) 
        while next is whitespace
        num = 0
        do 
            num = num * 10 + next
        while in.get(next) and next is digit
    //these are handy for initializing to known values.
    //I also have constructors that simply call these
    biguint& assign(const char* rhs, unsigned int base)
        for each char c in rhs
            data *= base
            add(baselut[c], 0)
    biguint& assign(const char* rhs, std::integral_constant base)
        for each char c in rhs
            data *= base
            add(base64lut[c], 0)
    //despite being 3 times as much, code, the hex version is _way_ faster.
    biguint& assign(const char* rhs, std::integral_constant) 
        if first two characters are "0x" skip them
        unsigned int len = strlen(rhs);
        grow(len/4+1);
        zero out data
        const unsigned int hex_per_int = uint_bits/4;
        if (len > hex_per_int*data.size()) { //calculate where first digit goes
            rhs += len-hex_per_int*data.size();
            len = hex_per_int*data.size();
        }
        for(unsigned int i=len; i --> 0; ) { //place each digit directly in it's place
            unsigned int t = (unsigned int)(baselut[*(rhs++)]) << (i%hex_per_int)*4u;
            data[i/hex_per_int] |= t;
        }
    

    I also made specializations for multiplication, divide, modulo, shifts and others for std::integral_constant, which made massive improvements to my serializing and deserializing functions amongst others.

    0 讨论(0)
提交回复
热议问题