模板:高精度
一个普普通通的压位大整数类
封装功能
-
通过整型、字符串的赋值与初始化方式 (默认初值为0)
Bign a(2147483648); a="234566464322469989856";
-
大整数类与大整数类 与 大整数类与整型 的加、减、乘
乘法未经过FFT优化 ( to-do++ )
Bign a,b;ll x; a*b+x-a;//混合类型运算时运算顺序不变但请不要将整型置于算式首:((a*b)+x)-a
-
大整数类与整型 的 除、取余
Bign a;ll b; a/b+a%b;
-
大整数与大整数 的 除、取余 (这里用的是倍增优化,FFT我太蒻了看不懂,可能会很慢慎用)
Bign a,b; a/b;
-
大整数类的位移操作 (这玩意建议最多不要位移超过10位,但对于少量的位移,效率还是会更高一点)
Bign a; a<<1;
-
大整数类与大整数类 的 各运算对应的赋值运算
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;
-
整合负数的大整数类 取绝对值
Bign a; cin>>a; cout<<abs(a)<<endl;
最大表示范围
为\(\displaystyle 10^{\ \text{MX_LEN}\ *\ lg(\ \text{BASE}\ ) }\) ,默认是\(10^{1010*4}=10^{4040}\)
常量参数调整
(在使用时尽可能调整合适的常数以达到效率最高)
const int MX_LEN=1010;
MX_LEN决定大整数类内数组大小,影响空间复杂度的主要因素,数值越大运算(越容易)越慢;同时也是储存数据范围的主要影响参数,在表示位数不够时请优先扩大MX_LEN。如果需要将MX_LEN改大,保险一点,一定一定要加上扩栈
const int BASE=10000;
决定大整数类压位大小(BASE==每一个数组元素表示的最大值+1),请保证使用10的整数次幂,数值越大运算(总体上)越快。取值的原则是在“进行需要的运算时不会溢出对应数据类型”的条件下尽可能大。推荐使用10000 ( \(10^4\) ):既可使BASE尽可能大,同时保证两个大整数类进行乘法运算时不会溢出。
- 如果想把 num 的数据类型改成 long long 的话( long long num[MX_LEN] ) ,推荐 BASE 的取值是 1e8 或者 1e9
- 如果不需要使用乘法的话,不改 long long 的话,推荐 BASE 的取值是 1e8 或者 1e9
- 如果不需要使用乘法的话,改 long long 的话,推荐 BASE 的取值是 1e18 并也换成 long long 类型
注意
- 关于代码里的_max其实就是一个自己写的max,直接用max应该也是可以的
#define _max(a,b) ((a)>(b)?(a):(b))
- 代码里有一部分循环变量使用了寄存器 register ,在代码里是简写为 R
#define R register
- 在数据10^10000以上时需要手动扩栈:
#pragma comment(linker, "/STACK:10240000,10240000")
模板代码
无负数版
const int BASE = 10000;
const int MX_LEN = 1010;
struct Bign {
int 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) const {
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) const {//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 int& num) const {
Bign c = *this;
c.len += 10;
for (R int i = 0; i < c.len; ++i) {
c.num[i] <<= num;
if (i && c.num[i - 1] >= BASE)
++c.num[i], c.num[i - 1] -= BASE;
}
c.clean();
return c;
}
Bign operator >> (const int& num) const {
Bign c = *this;
for (R int i = len - 1; i >= 0; --i) {
if ((c.num[i] & 1) && i)
c.num[i - 1] += BASE;
c.num[i] >>= num;
}
c.clean();
return c;
}
Bign operator * (const Bign& b) const {
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) const { //大数除以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) const {
Bign c, rest, now, _base;
now = *this;
rest = b;
_base = 1;
while (now >= rest) {
rest = rest << 1;
_base = _base << 1;
}
while (_base.len > 1 || _base.num[0]) {
if (now >= rest) {
now -= rest;
c += _base;
}
rest = rest >> 1;
_base = _base >> 1;
}
c.clean();
return c;
}
Bign operator % (const ll& b) const {
return (*this) - ((*this) / b) * b;
}
Bign operator % (const Bign& b) const {
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) const {
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) const {
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) const {
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) const {
return !((*this) == b);
}
bool operator <= (const Bign& b) const {
return !((*this) > b);
}
bool operator >= (const Bign& b) const {
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;
}
};
整合负数版
const int BASE = 10000;
const int MX_LEN = 1010;
struct Bign {
int num[MX_LEN];
int len;
int neg;
Bign() {
memset(num, 0, sizeof(num));
len = 1;
neg = 0;
}
Bign(const ll x) { *this = x; }
Bign(const string x) { *this = x; }
Bign(const Bign& x) {
memset(num, 0, sizeof(num));
len = x.len;
neg = x.neg;
for (R int i = 0; i < len; ++i)
num[i] = x.num[i];
}
void clean() {
while (num[len - 1] == 0 && len != 1)
--len;
if (len == 1 && num[0] == 0)
neg = 0;
}
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));
if (x[0] == '-')
neg = 1;
else
neg = 0;
ll temp = 0;
ll base = 1;
for (R int i = x.length() - 1; i >= neg; --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) const {
if (neg ^ b.neg) {
if (neg)
return b - (-*this);
else
return (*this) - (-b);
}
else {
Bign c;
if (neg)
c.neg = 1;
c.len = _max(len, b.len) + 1;
for (R 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) const {
if (neg ^ b.neg) {
if (neg)
return -((-*this) + b);
else
return (*this) + (-b);
}
else {
Bign c;
if (neg)
c.neg = 1;
if (abs(*this) < abs(b)) {
c.neg ^= 1;
c.len = _max(len, b.len);
for (R int i = 0; i < c.len; ++i) {
c.num[i] += b.num[i] - num[i];
if (c.num[i] < 0) {
c.num[i] += BASE;
c.num[i + 1] -= 1;
}
}
c.clean();
return c;
}
else {
c.len = _max(len, b.len);
for (R 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 c = *this;
c.neg ^= 1;
return c;
}
Bign operator * (const Bign& b) const {
Bign c;
c.len = len + b.len + 1;
for (R int i = 0; i < len; ++i) {
for (R int j = 0; j < b.len; ++j) {
c.num[i + j] += num[i] * b.num[j];
}
}
for (R int i = 0; i < c.len; ++i) {
c.num[i + 1] += c.num[i] / BASE;
c.num[i] %= BASE;
}
if (neg ^ b.neg)
c.neg = 1;
c.clean();
return c;
}
Bign operator / (const ll& b) const {
Bign c;
c.len = len;
ll rest = 0;
for (R int i = len - 1; i >= 0; --i) {
rest = rest * BASE + num[i];
c.num[i] = rest / b;
rest %= b;
}
if (neg ^ (b < 0))
c.neg = 1;
c.clean();
return c;
}
Bign operator / (const Bign& b) const {
Bign c, rest, now, _base;
now = abs(*this);
rest = abs(b);
_base = 1;
while (now >= rest) {
rest <<= 1;
_base <<= 1;
}
while (_base.len > 1 || _base.num[0]) {
if (now >= rest) {
now -= rest;
c += _base;
}
rest >>= 1;
_base >>= 1;
}
if (neg ^ b.neg)
c.neg = 1;
c.clean();
return c;
}
Bign operator << (const int& num) const {
Bign c = *this;
c.len += 10;
for (R int i = 0; i < c.len; ++i) {
c.num[i] <<= num;
if (i && c.num[i - 1] >= BASE)
++c.num[i], c.num[i - 1] -= BASE;
}
c.clean();
return c;
}
Bign operator >> (const int& num) const {
Bign c = *this;
for (R int i = len - 1; i >= 0; --i) {
if ((c.num[i] & 1) && i)
c.num[i - 1] += BASE;
c.num[i] >>= num;
}
c.clean();
return c;
}
Bign operator % (const ll& b) const {
return (*this) - ((*this) / b) * b;
}
Bign operator % (const Bign& b) const {
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;
}
Bign operator <<= (const int& num) {
return (*this) = (*this) << num;
}
Bign operator >>= (const int& num) {
return (*this) = (*this) >> num;
}
bool operator < (const Bign& b) const {
if (neg && !b.neg)
return 1;
if (!neg && b.neg)
return 0;
if (neg) {
if (len == b.len) {
for (R 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;
}
else {
if (len == b.len) {
for (R 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) const {
if (neg && !b.neg)
return 0;
if (!neg && b.neg)
return 1;
if (neg) {
if (len == b.len) {
for (R 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;
}
else {
if (len == b.len) {
for (R 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) const {
if (neg != b.neg)
return 0;
if (len == b.len) {
for (R int i = len - 1; i >= 0; --i) {
if (num[i] != b.num[i])
return 0;
}
return 1;
}
return 0;
}
bool operator != (const Bign& b) const {
return !((*this) == b);
}
bool operator <= (const Bign& b) const {
return !((*this) > b);
}
bool operator >= (const Bign& b) const {
return !((*this) < b);
}
friend Bign abs(const Bign& x) {
Bign c = x;
c.neg = 0;
return c;
}
friend ostream& operator << (ostream& out, const Bign& x) {
if (x.neg)
out << '-';
out << x.num[x.len - 1];
for (R 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;
}
};