#include "lint.hpp" void get(vector< complex > x) { for(uint i = x.size() - 1; i >= 0; i--) { if(i > x.size()) break; cout << x[i] << " "; } cout << endl << endl; } void get(vuint x) { for(uint i = x.size() - 1; i >= 0; i--) { if(i > x.size()) break; cout << x[i] << " "; } cout << endl << endl; } lint::lint() { } lint::lint(string lintin) { operator =(lintin); } lint::~lint() { num.clear(); } void lint::operator =(string strin) { sign = 1; strin = del(strin); if(strin[0] == '-') { sign = -1; strin = strin.substr(1, strin.size() - 1); } /* 整理输入,使其全是数字,并且首位无0 */ for(uint i = 0; i < strin.size(); i++) if(strin[i] > '9' || strin[i] < '0') strin[i] = '0'; length = strin.size(); len = (length + unit - 1) / unit; uint mod = length % unit; if(num.capacity()) num.clear(); num.resize(len); for(uint i = 0; i < len - 1; i++) num[i] = atoi(strin.substr(length - (i + 1) * unit, unit).c_str()); num[len - 1] = atoi(strin.substr(0, (mod == 0) ? unit : mod).c_str()); } /* 提取十进制数值 */ string lint::getd() { return vtos(num); } vuint lint::getvec() { return num; } /* 提取 vector 中相应位置的数字 */ uint lint::operator [](uint locale) { if(locale >= len) return 0; else return num[locale]; } /* 提取 vector 的长度 */ uint lint::getlen() { return len; } /* 提取整数长度 */ uint lint::getlength() { return length; } int lint::getsign() { return sign; } /* 定义加法 */ string lint::operator +(lint opnum) { if(sign * opnum.getsign() == -1) { if(sign == -1) { lint abs(getd()); return opnum - abs; } else { lint abs(opnum.getd()); lint absa(getd()); return absa - abs; } } else { vuint sumint(1); vuint sumshort(1); if(len >= opnum.getlen()) { sumint.resize(len); sumint = getvec(); sumshort = opnum.getvec(); } else { sumint.resize(opnum.getlen()); sumint = opnum.getvec(); sumshort = getvec(); } sumint.resize(sumint.size() + 1); sumint[sumint.size()] = 0; uint temp; for(uint i = 0; i < sumshort.size(); i++) { temp = sumint[i] + sumshort[i]; sumint[i] = temp % cunit; sumint[i + 1] += temp / cunit; } for(uint i = sumshort.size(); i < sumint.size() - 1; i++) { temp = sumint[i]; sumint[i] = temp % cunit; sumint[i + 1] += temp / cunit; } if(sign == -1) return "-" + vtos(sumint); else return vtos(sumint); } } string lint::operator -(lint opnum) { if(sign * opnum.getsign() == -1) { if(sign == 1) return operator +(opnum); else return "-" + operator +(opnum); } else { vuint difint(len >= opnum.getlen() ? len : opnum.getlen()); vuint small(len >= opnum.getlen() ? opnum.getlen() : len); if(compare(opnum) >= 0) { difint = num; small = opnum.getvec(); } else { difint = opnum.getvec(); small = num; } for(uint i = small.size() - 1; i >= 0; i--) { if(i > small.size()) break; if(difint[i] < small[i]) { uint temp = i + 1; while(difint[temp] == 0) { difint[temp] = cunit - 1; temp++; if(temp >= difint.size()) break; } if(temp < difint.size()) difint[temp]--; difint[i] += cunit; } difint[i] -= small[i]; } if(sign * compare(opnum) == 1) return vtos(difint); else return "-" + vtos(difint); } } /* 定义乘法,用 FFT 实现 */ string lint::operator *(lint opnum) { uint a_size = len, b_size = opnum.getlen(); vector< complex > a(a_size), b(b_size); for(uint i = 0; i < a_size; i++) a[i].real() = num[i]; for(uint i = 0; i < b_size; i++) b[i].real() = (opnum[i]); uint n; a_size += b_size; for (n = a_size; n != (n&-n); n += (n&-n)); a.resize(n); b.resize(n); FFT(a, n); FFT(b, n); for (uint i = 0; i < n; i++) a[i] *= b[i]; IFFT(a, n); for (uint i = 0; i < a_size-1; i++) { a[i + 1] += a[i].real() / 1000.; a[i] = fmodl(a[i].real(), 1000.L); a[i].real() += eps; } vuint mulout(n); for(uint i = 0; i < a.size(); i++) mulout[i] = a[i].real(); if(sign * opnum.getsign() == -1) return "-" + vtos(mulout); else return vtos(mulout); } int lint::operator ==(lint opnum) { if(sign * opnum.getsign() > 0) { if(sign == 1) return compare(opnum); if(sign == -1) return -(compare(opnum)); else return 0; } else { if(sign == 1) return 1; else return -1; } } int lint::compare(lint opnum) { if(length > opnum.getlength()) return 1; if(length < opnum.getlength()) return -1; else { for(uint i = len - 1; i >= 0; i--) { if(i > len - 1) break; if(num[i] > (opnum[i])) return 1; if(num[i] < (opnum[i])) return -1; } return 0; } } /* 定义除法 */ string lint::operator /(lint opnum) { if(compare(opnum) == -1) return "0"; if(compare(opnum) == 0) return "1"; else { uint move = len - opnum.getlen(); vuint devint(move + 1); vuint open = getvec(); open.resize(len + 1); open[len] = 0; for(uint i = move; i >= 0; i--) { if(i > move) break; uint high = i + opnum.getlen() - 1; if(open.capacity() <= high) { open.resize(high + 2); open[high + 1] = 0; } uint temp = (open[high] + open[high + 1] * cunit) / opnum.getvec().back() + 2; vuint tryvec; int count = 1; do { if(--temp > cunit * cunit) temp = 1; tryvec = vmul(opnum.getvec(), temp, i); count++; } while(vless(open, tryvec) && count < 20); devint[i] = temp; open = vdif(open, tryvec); open[open.size()] = 0; tryvec.clear(); } if(sign * opnum.getsign() == 1) return vtos(devint); else return "-" + vtos(devint); } } string lint::operator %(lint opnum) { if(sign == 1 && compare(opnum) == -1) return getd(); else { lint div = getd(); lint q = (div / opnum); lint mod = (div - (q * opnum)); if(sign == 1) return mod.getd(); else return (opnum - mod); } } vuint lint::getbit() { vuint out(len * 3); lint opnum = getd(); lint bit("2"); uint i; for(i = 0; i < len * 3; i++) { if(opnum % bit == "1") out[i] = 1; else out[i] = 0; opnum = opnum / bit; } while(opnum.getd() != "0") { out.resize(i + 2); if(opnum % bit == "1") out[i] = 1; else out[i] = 0; opnum = opnum / bit; i++; } return del(out); } string lint::operator ^(lint opnum) { lint power("1"); lint base = getd(); for(uint i = opnum.getbit().size() - 1; i >= 0; i--) { if(i > opnum.getbit().size()) break; power = (power * power); if(opnum.getbit()[i] == 1) power = (power * base); } return del(power.getd()); } /* 消去首位0 */ string del(string undel) { uint flag = 0; while(undel.substr(0, 2) == "--") undel = undel.substr(2, undel.size() - 2); if(undel[0] == '-') { undel = undel.substr(1, undel.size() - 1); flag = 1; } while(undel.size() > 1 && undel[0] == '0') undel = undel.substr(1, undel.size() - 1); if(undel.size() == 1 && undel[0] == '0') return "0"; if(flag) return "-" + undel; return undel; } vuint del(vuint undel) { while(undel[undel.size() - 1] == 0) undel.pop_back(); vuint out(undel.size()); for(uint i = 0; i < undel.size(); i++) out[i] = undel[i]; return out; } /* 整数到字符串的转换 */ string itos(uint intin) { string strout = ""; if(intin == 0) return "0"; while(intin > 0) { char temp = intin % carry + '0'; strout = temp + strout; intin /= carry; } return strout; } /* 向量到字符串的转换 */ string vtos(vuint vin) { string strout = ""; string temp = ""; for(uint i = vin.size() - 1; i >= 0; i--) { if(i > vin.size() - 1) break; temp = itos(vin[i] % cunit); while(temp.size() < unit) temp = "0" + temp; strout += temp; } return del(strout); } /** 向量转比特流 string vtobit(vuint vin) { string strout = ""; for(uint i = vin.size() - 1; i >= 0; i--) { if(i > vin.size()) break; if(vin[i]) strout += "1"; else strout += "0"; } return del(strout); }*/ /* 向量和整数的乘法 */ vuint vmul(vuint op, uint opnum, uint power = 0) { if(power) { op.resize(op.size() + power); for(uint i = op.size() - 1; i >= power; i--) { if(i > op.size()) break; op[i] = op[i - power]; } for(uint i = power - 1; i >= 0; i--) { if(i > op.size()) break; op[i] = 0; } } lint big(vtos(op)); lint small(itos(opnum)); lint out(big * small); return out.getvec(); } /* 向量减法 */ vuint vdif(vuint big, vuint small) { lint bigint(vtos(big)); lint smallint(vtos(small)); if(bigint.compare(smallint) == -1) return big; else { lint out(bigint - smallint); return out.getvec(); } } /* 比较大小 */ uint vless(vuint big, vuint small) { lint bigint(vtos(big)); lint smallint(vtos(small)); if(bigint.compare(smallint) == -1) return 1; else return 0; } /* 快速傅立叶变换 */ void FFT(vector< complex > &x, uint n) { uint i,j,k,t; for (i = 0; i < n; ++i) { j = 0; for (t = i, k = n; k /= 2; t /= 2) j = j*2+t%2; if (j > i) swap(x[j], x[i]); } for (k = 2; k <= n; k *= 2) { const complex omega_unit(cosl(2*PI/k), sinl(2*PI/k)); for (i = 0; i < n; i += k) { complex omega(1, 0); for (j = 0; j < k/2; ++j) { complex t = omega*x[i+j+k/2]; x[i+j+k/2] = x[i+j]-t; x[i+j] += t; omega *= omega_unit; } } } } void IFFT(vector< complex > &x, uint n) { uint i,j,k,t; for (i = 0; i < n; ++i) { j = 0; for (t = i, k = n; k /= 2; t /= 2) j = j*2+t%2; if (j > i) swap(x[j], x[i]); } for (k = 2; k <= n; k *= 2) { const complex omega_unit(cosl(-2*PI/k), sinl(-2*PI/k)); for (i = 0; i < n; i += k) { complex omega(1, 0); for (j = 0; j < k/2; ++j) { complex t = omega*x[i+j+k/2]; x[i+j+k/2] = x[i+j]-t; x[i+j] += t; omega *= omega_unit; } } } for (i = 0; i < n; ++i) x[i] /= n; } /* 求两数最大公约数 */ string gcd(lint a, lint b) { if(b.getd() == "0") return a.getd(); else { lint newb = a % b; return gcd(b, newb); } }