一个普普通通的压位大整数类,包含以下功能:(在使用时尽可能删减并调整合适的常数以达到效率最高)
?
-
通过整型、字符串的赋值与初始化方式 (默认初值为0)
Bign a(2147483648); a="234566464322469989856";
-
大整数类与大整数类 与 大整数类与整型 的加、减、乘
Bign a,b;ll x; a*b+x-a;//混合类型运算时运算顺序不变但请不要将整型置于算式首:((a*b)+x)-a
-
大整数类与整型 的 除、取余
Bign a;ll b; a/b+a%b;
-
大整数与大整数 的 除、取余(这个会很慢慎用)Bign a,b; a/b;
-
大整数类与大整数类 的 各运算对应的赋值运算
Bign a,b; a*=b;
-
大整数类与大整数类 与 大整数类与整型 的 比较运算
Bign a,b;ll c if(a<=b || (a!=c && a>b))
-
大整数类 通过 cin、cout的输入输出
Bign a; cin>>a; cout<<a+1<<endl;
注意在使用时需要用到以下常量:
-
const int MX_LEN=1010;
决定大整数类内数组大小,数值越大运算(越容易)越慢
-
const int BASE=10000;
决定大整数类压位大小(每一个数组元素表示的最大值+1),数值越大运算(总体上)越快。推荐使用10000:既可使BASE尽可能大,同时保证两个大整数类进行乘法运算时不会溢出(当然如果想改成longlong那就不存在了)
最大表示范围为\(\displaystyle 10^{\ \mbox{MX_LEN}\ * lg(\mbox{BASE}) }\)? ,默认是\(10^{1010*4}=10^{4040}\)????
以及需要以下函数
-
int _max(int a,int b){return (a>b?a:b);}
模板代码如下:
inline ll _max(ll a, ll b) {
return a > b ? a : b;
}
const int BASE = 10000;
const int MX_LEN = 1010;
struct Bign {
ll num[MX_LEN];
int len;
Bign() {
memset(num, 0, sizeof(num));
len = 1;
}
Bign(const ll x) { *this = x; }
Bign(const string x) { *this = x; }
Bign(const Bign& x) {
memset(num, 0, sizeof(num));
len = x.len;
for (int i = 0; i < len; i++)
num[i] = x.num[i];
}
void clean() {
while (num[len - 1] == 0 && len != 1)
len--;
}
Bign operator = (const ll x) {
stringstream ss;
ss << x;
string temp;
ss >> temp;
return *this = temp;
}
Bign operator = (const string x) {
len = 0;
memset(num, 0, sizeof(num));
ll temp = 0;
ll base = 1;
for (int i = x.length() - 1; i >= 0; i--) {
temp += (x[i] - ‘0‘) * base;
base *= 10;
if (base == BASE) {
num[len++] = temp;
temp = 0;
base = 1;
}
}
num[len++] = temp;
clean();
return *this;
}
Bign operator + (const Bign& b) {
Bign c;
c.len = _max(len, b.len) + 1;
for (int i = 0; i < c.len; i++) {
c.num[i] += num[i] + b.num[i];
c.num[i + 1] += c.num[i] / BASE;
c.num[i] %= BASE;
}
c.clean();
return c;
}
Bign operator - (const Bign& b) {//a-b保证a>b
Bign c;
c.len = _max(len, b.len);
for (int i = 0; i < c.len; i++) {
c.num[i] += num[i] - b.num[i];
if (c.num[i] < 0) {
c.num[i] += BASE;
c.num[i + 1] -= 1;
}
}
c.clean();
return c;
}
Bign operator * (const Bign& b) {
Bign c;
c.len = len + b.len + 5;
for (int i = 0; i < c.len; i++) {
for (int j = 0; j < b.len; j++) {
c.num[i + j] += num[i] * b.num[j];
c.num[i + j + 1] += c.num[i + j] / BASE;
c.num[i + j] %= BASE;
}
}
c.clean();
return c;
}
Bign operator / (const ll& b) { //大数除以long long
Bign c;
c.len = len;
ll rest = 0;
for (int i = len - 1; i >= 0; i--) {
rest = rest * BASE + num[i];
c.num[i] = rest / b;
rest %= b;
}
c.clean();
return c;
}
Bign operator / (const Bign& b) {//大数除以大数
Bign c, rest;
c.len = len;
for (int i = len - 1; i >= 0; i--) {
rest = rest * BASE + num[i];
while (rest >= b) {
c.num[i]++;
rest = rest - b;
}
}
c.clean();
return c;
}
Bign operator % (const ll& b) {
return (*this) - ((*this) / b) * b;
}
Bign operator % (const Bign& b) {
return (*this) - ((*this) / b) * b;
}
Bign operator += (const Bign& b) {
return (*this) = (*this) + b;
}
Bign operator -= (const Bign& b) {
return (*this) = (*this) - b;
}
Bign operator *= (const Bign& b) {
return (*this) = (*this) * b;
}
Bign operator /= (const ll& b) {
return (*this) = (*this) / b;
}
Bign operator /= (const Bign& b) {
return (*this) = (*this) / b;
}
Bign operator %= (const ll& b) {
return (*this) = (*this) % b;
}
Bign operator %= (const Bign& b) {
return (*this) = (*this) % b;
}
bool operator < (const Bign& b) {
if (len == b.len) {
for (int i = len - 1; i >= 0; i--) {
if (num[i] != b.num[i])
return num[i] < b.num[i];
}
return 0;
}
return len < b.len;
}
bool operator > (const Bign& b) {
if (len == b.len) {
for (int i = len - 1; i >= 0; i--) {
if (num[i] != b.num[i])
return num[i] > b.num[i];
}
return 0;
}
return len > b.len;
}
bool operator == (const Bign& b) {
if (len == b.len) {
for (int i = len - 1; i >= 0; i--) {
if (num[i] != b.num[i])
return 0;
}
return 1;
}
return 0;
}
bool operator != (const Bign& b) {
return !((*this) == b);
}
bool operator <= (const Bign& b) {
return !((*this) > b);
}
bool operator >= (const Bign& b) {
return !((*this) < b);
}
friend ostream& operator << (ostream& out, const Bign& x) {
out << x.num[x.len - 1];
for (int i = x.len - 2; i >= 0; i--) {
int t = BASE / 10;
while (x.num[i] < t && t>1) {
out << 0;
t /= 10;
}
out << x.num[i];
}
return out;
}
friend istream& operator >> (istream& in, Bign& x) {
string temp;
in >> temp;
x = temp;
return in;
}
};