|
@@ -2,16 +2,18 @@
|
|
|
#define BIGINT64_HPP
|
|
|
#include <cstdint>
|
|
|
#include <cstdlib>
|
|
|
+#include <cmath>
|
|
|
+#include <cassert>
|
|
|
#include <algorithm>
|
|
|
#include <iterator>
|
|
|
+#include <limits>
|
|
|
#include <initializer_list>
|
|
|
#include <deque>
|
|
|
#include <vector>
|
|
|
#include <string>
|
|
|
-#include <cmath>
|
|
|
#include <bitset>
|
|
|
#include <iostream>
|
|
|
-const std::vector<char> chars = {'0','1','2','3','4','5','6','7','8','9'};
|
|
|
+const std::vector<char> chars = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
|
|
|
const __uint128_t _m = ((__uint128_t)1) << 64;
|
|
|
template<typename T>
|
|
|
inline int signum(T t){
|
|
@@ -32,14 +34,18 @@ struct BigInt{
|
|
|
using uint64_t = std::uint64_t;
|
|
|
using uint32_t = std::uint32_t;
|
|
|
using lui = ::__uint128_t;
|
|
|
+ using iterator = std::deque<uint64_t>::iterator;
|
|
|
+ using const_iterator = std::deque<uint64_t>::const_iterator;
|
|
|
+ using reverse_iterator = std::deque<uint64_t>::reverse_iterator;
|
|
|
+ using const_reverse_iterator = std::deque<uint64_t>::const_reverse_iterator;
|
|
|
std::deque<uint64_t> data;
|
|
|
int signum;
|
|
|
inline BigInt() : data(1,0),signum(1){}
|
|
|
inline BigInt(size_t _s, uint64_t fill) : data(_s,fill), signum(1){}
|
|
|
- inline BigInt(int a) : signum(::signum(a)), data(1, std::abs(a)){}
|
|
|
- inline BigInt(unsigned int a) : signum(1), data(1, a){}
|
|
|
- inline BigInt(unsigned long long a) : signum(1), data(1, a){}
|
|
|
- inline BigInt(long long a) : signum(::signum(a)), data(1, std::abs(a)){}
|
|
|
+ inline BigInt(int a) : data(1, std::abs(a)),signum(::signum(a)){}
|
|
|
+ inline BigInt(unsigned int a) : data(1, a),signum(1){}
|
|
|
+ inline BigInt(unsigned long long a) : data(1, a), signum(1){}
|
|
|
+ inline BigInt(long long a) : data(1, std::abs(a)),signum(::signum(a)){}
|
|
|
inline BigInt(const std::initializer_list<uint64_t>& l) : data(l), signum(1){}
|
|
|
inline BigInt(std::initializer_list<uint64_t>&& l) : data(std::move(l)), signum(1){}
|
|
|
template<typename InputIterator>
|
|
@@ -52,15 +58,152 @@ struct BigInt{
|
|
|
std::deque<uint64_t>::const_iterator end()const{return data.end();}
|
|
|
std::deque<uint64_t>::const_reverse_iterator rbegin()const{return data.rbegin();}
|
|
|
std::deque<uint64_t>::const_reverse_iterator rend()const{return data.rend();}
|
|
|
+ uint64_t& operator[](size_t i){return data[i];}
|
|
|
+ const uint64_t& operator[](size_t i)const{return data[i];}
|
|
|
size_t size()const{return data.size();}
|
|
|
- auto cbegin(){return data.cbegin();}
|
|
|
- auto cend(){return data.cend();}
|
|
|
- auto crbegin(){return data.crbegin();}
|
|
|
- auto crend(){return data.crend();}
|
|
|
auto cbegin()const{return data.cbegin();}
|
|
|
auto cend()const{return data.cend();}
|
|
|
auto crbegin()const{return data.crbegin();}
|
|
|
auto crend()const{return data.crend();}
|
|
|
+ inline bool operator<(const BigInt& o)const{
|
|
|
+ if(signum > o.signum){
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if(signum < o.signum){
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ const_iterator it1 = begin();
|
|
|
+ const_iterator it2 = o.begin();
|
|
|
+ if(size() > o.size()){
|
|
|
+ it1 += size() - o.size();
|
|
|
+ auto _t = begin();
|
|
|
+ while(_t != it1)
|
|
|
+ if(*_t)return false;
|
|
|
+ }
|
|
|
+ else if(size() < o.size()){
|
|
|
+ it2 += o.size() - size();
|
|
|
+ auto _t = o.begin();
|
|
|
+ while(_t != it2)
|
|
|
+ if(*_t)return true;
|
|
|
+ }
|
|
|
+ while(it1 != end() && it2 != o.end()){
|
|
|
+ if(*(it1) < *(it2))return true;
|
|
|
+ if(*(it1) > *(it2))return false;
|
|
|
+ ++it1;++it2;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ inline bool operator>(const BigInt& o)const{
|
|
|
+ if(signum < o.signum){
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if(signum > o.signum){
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ const_iterator it1 = begin();
|
|
|
+ const_iterator it2 = o.begin();
|
|
|
+ if(size() > o.size()){
|
|
|
+ it1 += size() - o.size();
|
|
|
+ auto _t = begin();
|
|
|
+ while(_t != it1)
|
|
|
+ if(*_t)return true;
|
|
|
+ }
|
|
|
+ else if(size() < o.size()){
|
|
|
+ it2 += o.size() - size();
|
|
|
+ auto _t = o.begin();
|
|
|
+ while(_t != it2)
|
|
|
+ if(*_t)return false;
|
|
|
+ }
|
|
|
+ while(it1 != end() && it2 != o.end()){
|
|
|
+ if(*(it1) > *(it2))return true;
|
|
|
+ if(*(it1) < *(it2))return false;
|
|
|
+ ++it1;++it2;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ inline bool operator<=(const BigInt& o)const{
|
|
|
+ if(signum > o.signum){
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if(signum < o.signum){
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ const_iterator it1 = begin();
|
|
|
+ const_iterator it2 = o.begin();
|
|
|
+ if(size() > o.size()){
|
|
|
+ it1 += size() - o.size();
|
|
|
+ auto _t = begin();
|
|
|
+ while(_t != it1)
|
|
|
+ if(*_t)return true;
|
|
|
+ }
|
|
|
+ else if(size() < o.size()){
|
|
|
+ it2 += o.size() - size();
|
|
|
+ auto _t = o.begin();
|
|
|
+ while(_t != it2)
|
|
|
+ if(*_t)return false;
|
|
|
+ }
|
|
|
+ while(it1 != end() && it2 != o.end()){
|
|
|
+ if(*(it1) < *(it2))return true;
|
|
|
+ if(*(it1) > *(it2))return false;
|
|
|
+ ++it1;++it2;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ inline bool operator>=(const BigInt& o)const{
|
|
|
+ if(signum < o.signum){
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if(signum > o.signum){
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ const_iterator it1 = begin();
|
|
|
+ const_iterator it2 = o.begin();
|
|
|
+ if(size() > o.size()){
|
|
|
+ it1 += size() - o.size();
|
|
|
+ auto _t = begin();
|
|
|
+ while(_t != it1)
|
|
|
+ if(*_t)return true;
|
|
|
+ }
|
|
|
+ else if(size() < o.size()){
|
|
|
+ it2 += o.size() - size();
|
|
|
+ auto _t = o.begin();
|
|
|
+ while(_t != it2)
|
|
|
+ if(*_t)return false;
|
|
|
+ }
|
|
|
+ while(it1 != end() && it2 != o.end()){
|
|
|
+ if(*(it1) > *(it2))return true;
|
|
|
+ if(*(it1) < *(it2))return false;
|
|
|
+ ++it1;++it2;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ inline bool operator==(const BigInt& o)const{
|
|
|
+ if(signum < o.signum){
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if(signum > o.signum){
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ const_iterator it1 = begin();
|
|
|
+ const_iterator it2 = o.begin();
|
|
|
+ if(size() > o.size()){
|
|
|
+ it1 += size() - o.size();
|
|
|
+ auto _t = begin();
|
|
|
+ while(_t != it1)
|
|
|
+ if(*_t)return false;
|
|
|
+ }
|
|
|
+ else if(size() < o.size()){
|
|
|
+ it2 += o.size() - size();
|
|
|
+ auto _t = o.begin();
|
|
|
+ while(_t != it2)
|
|
|
+ if(*_t)return false;
|
|
|
+ }
|
|
|
+ while(it1 != end() && it2 != o.end()){
|
|
|
+ if(*(it1) != *(it2))return false;
|
|
|
+ ++it1;++it2;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
inline bool isZero()const{
|
|
|
for(auto it = data.begin();it != data.end();it++){
|
|
|
if(*it)return false;
|
|
@@ -108,7 +251,7 @@ struct BigInt{
|
|
|
}
|
|
|
inline BigInt& chunkshiftLeft(int c){
|
|
|
if(c < 0)return chunkshiftRight(-c);
|
|
|
- if(c >= size()){std::fill(begin(),end(),0);return *this;}
|
|
|
+ if((unsigned int)c >= size()){std::fill(begin(),end(),0);return *this;}
|
|
|
auto it1 = data.begin();
|
|
|
auto it2 = it1 + c;
|
|
|
while(it2 != data.end())*(it1++) = *(it2++);
|
|
@@ -117,13 +260,18 @@ struct BigInt{
|
|
|
}
|
|
|
inline BigInt& chunkshiftRight(int c){
|
|
|
if(c < 0)return chunkshiftLeft(-c);
|
|
|
- if(c >= size()){std::fill(begin(),end(),0);return *this;}
|
|
|
+ if((unsigned int)c >= size()){std::fill(begin(),end(),0);return *this;}
|
|
|
auto it1 = data.rbegin();
|
|
|
auto it2 = it1 + c;
|
|
|
while(it2 != data.rend())*(it1++) = *(it2++);
|
|
|
while(it1 != data.rend())*(it1++) = 0;
|
|
|
return *this;
|
|
|
}
|
|
|
+ inline BigInt add(const BigInt& o){
|
|
|
+ BigInt ret = *this;
|
|
|
+ ret.adda(o);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
inline BigInt& adda(const BigInt& o){
|
|
|
while(size() < o.size())data.push_front(0);
|
|
|
bool carry = 0;
|
|
@@ -141,10 +289,25 @@ struct BigInt{
|
|
|
if(carry)data.push_front(1);
|
|
|
return *this;
|
|
|
}
|
|
|
-
|
|
|
- inline BigInt mult(const BigInt& o){
|
|
|
- BigInt result(size() + o.size(),0);
|
|
|
- BigInt temp(size() + o.size(),0);
|
|
|
+ inline BigInt& suba(const BigInt& o){
|
|
|
+ assert((*this) >= (o));
|
|
|
+ bool carry = 0;
|
|
|
+ auto it1 = rbegin();
|
|
|
+ auto it2 = o.rbegin();
|
|
|
+ while(it1 != rend() && it2 != o.rend()){
|
|
|
+ carry = __builtin_usubll_overflow(*it1 - carry, *it2, (unsigned long long*)(&(*it1)));
|
|
|
+ carry |= ((*it1 - carry) == std::numeric_limits<uint64_t>::max());
|
|
|
+ it1++;
|
|
|
+ it2++;
|
|
|
+ }
|
|
|
+ while(it1 != rend() && carry){
|
|
|
+ carry = __builtin_usubll_overflow(*it1, carry, (unsigned long long*)(&(*it1)));
|
|
|
+ }
|
|
|
+ return *this;
|
|
|
+ }
|
|
|
+ inline BigInt mult(const BigInt& o)const{
|
|
|
+ BigInt result(size() + o.size() + 1,0);
|
|
|
+ BigInt temp(size() + o.size() + 1,0);
|
|
|
int p = 0;
|
|
|
for(auto it1 = rbegin();it1 != rend();it1++){
|
|
|
auto it = temp.rbegin();
|
|
@@ -155,7 +318,7 @@ struct BigInt{
|
|
|
*(it++) = (uint64_t)prod;
|
|
|
carry = (prod >> 64);
|
|
|
}
|
|
|
- if(carry)(*it)++;
|
|
|
+ if(carry)(*it) += carry;
|
|
|
temp.chunkshiftLeft(p++);
|
|
|
result.adda(temp);
|
|
|
temp.setZero();
|
|
@@ -164,13 +327,48 @@ struct BigInt{
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
+ inline std::string rawString(){
|
|
|
+ std::string s = "";
|
|
|
+ bool flag;
|
|
|
+ for(unsigned int i = 0;i < size();i++){
|
|
|
+ if(data[i])flag = true;
|
|
|
+ if(flag);
|
|
|
+ s += std::to_string(data[i]);
|
|
|
+ if(i < size() - 1)s += "|";
|
|
|
+ }
|
|
|
+ return s;
|
|
|
+ }
|
|
|
+
|
|
|
inline std::string toString(){
|
|
|
+ std::deque<char> c_str;
|
|
|
+ const uint64_t q = 1000000000000000000ULL;
|
|
|
+ //c_str.reserve(size() * 19);
|
|
|
+ BigInt diver = *this;
|
|
|
+ while(!diver.isZero()){
|
|
|
+ std::string frac = std::to_string(diver.mod(q));
|
|
|
+ int a = 0;
|
|
|
+ for(auto it = frac.rbegin();it != frac.rend();it++){
|
|
|
+ c_str.push_front(*it);
|
|
|
+ a++;
|
|
|
+ }
|
|
|
+ while(a < 18){
|
|
|
+ c_str.push_front('0');
|
|
|
+ a++;
|
|
|
+ }
|
|
|
+ diver.div(q);
|
|
|
+ }
|
|
|
+ auto it = c_str.begin();
|
|
|
+ while(*(it) == '0')++it;
|
|
|
+ return std::string(it, c_str.end());
|
|
|
+ }
|
|
|
+
|
|
|
+ inline std::string toString(unsigned int base){
|
|
|
std::vector<char> c_str;
|
|
|
- c_str.reserve(data.size() * 19);
|
|
|
+ c_str.reserve(size() * (unsigned int)(64.0 * std::log(2) / std::log((double)base)));
|
|
|
BigInt diver = *this;
|
|
|
while(!diver.isZero()){
|
|
|
- c_str.push_back(chars.at(diver.mod(10)));
|
|
|
- diver.div(10);
|
|
|
+ c_str.push_back(chars.at(diver.mod(base)));
|
|
|
+ diver.div(base);
|
|
|
}
|
|
|
return std::string(c_str.rbegin(), c_str.rend());
|
|
|
}
|