标签:stat cto pre ble 一个 air i++ span event
本人的java不是很擅长的人来说,大数敲起来是一个很麻烦的事。不过有了一个大数非常好的板子(很佩服写这个板子的大佬),很好的解决了这个问题,这个板子 加 减 乘 除 取余,求GCD等等都可以解决。只需要定义 bigint 就可以使用强大的功能。
请看这个代码。
1 const int base = 1000000000; 2 const int base_digits = 9; 3 struct bigint { 4 vector<int> z; 5 int sign; 6 bigint() : sign(1) {} 7 bigint(long long v) { *this = v; } 8 bigint &operator=(long long v) { 9 sign = v < 0 ? -1 : 1; 10 v *= sign; 11 z.clear(); 12 for (; v > 0; v = v / base) z.push_back((int)(v % base)); 13 return *this; 14 } 15 16 bigint(const string &s) { read(s); } 17 18 bigint &operator+=(const bigint &other) { 19 if (sign == other.sign) { 20 for (int i = 0, carry = 0; i < other.z.size() || carry; ++i) { 21 if (i == z.size()) 22 z.push_back(0); 23 z[i] += carry + (i < other.z.size() ? other.z[i] : 0); 24 carry = z[i] >= base; 25 if (carry) 26 z[i] -= base; 27 } 28 } 29 else if (other != 0 /* prevent infinite loop */) { 30 *this -= -other; 31 } 32 return *this; 33 } 34 35 friend bigint operator+(bigint a, const bigint &b) { return a += b; } 36 37 bigint &operator-=(const bigint &other) { 38 if (sign == other.sign) { 39 if (sign == 1 && *this >= other || sign == -1 && *this <= other) { 40 for (int i = 0, carry = 0; i < other.z.size() || carry; ++i) { 41 z[i] -= carry + (i < other.z.size() ? other.z[i] : 0); 42 carry = z[i] < 0; 43 if (carry) 44 z[i] += base; 45 } 46 trim(); 47 } 48 else { 49 *this = other - *this; 50 this->sign = -this->sign; 51 } 52 } 53 else { 54 *this += -other; 55 } 56 return *this; 57 } 58 59 friend bigint operator-(bigint a, const bigint &b) { return a -= b; } 60 61 bigint &operator*=(int v) { 62 if (v < 0) sign = -sign, v = -v; 63 for (int i = 0, carry = 0; i < z.size() || carry; ++i) { 64 if (i == z.size()) 65 z.push_back(0); 66 long long cur = (long long)z[i] * v + carry; 67 carry = (int)(cur / base); 68 z[i] = (int)(cur % base); 69 } 70 trim(); 71 return *this; 72 } 73 74 bigint operator*(int v) const { return bigint(*this) *= v; } 75 76 friend pair<bigint, bigint> divmod(const bigint &a1, const bigint &b1) { 77 int norm = base / (b1.z.back() + 1); 78 bigint a = a1.abs() * norm; 79 bigint b = b1.abs() * norm; 80 bigint q, r; 81 q.z.resize(a.z.size()); 82 83 for (int i = (int)a.z.size() - 1; i >= 0; i--) { 84 r *= base; 85 r += a.z[i]; 86 int s1 = b.z.size() < r.z.size() ? r.z[b.z.size()] : 0; 87 int s2 = b.z.size() - 1 < r.z.size() ? r.z[b.z.size() - 1] : 0; 88 int d = (int)(((long long)s1 * base + s2) / b.z.back()); 89 r -= b * d; 90 while (r < 0) 91 r += b, --d; 92 q.z[i] = d; 93 } 94 95 q.sign = a1.sign * b1.sign; 96 r.sign = a1.sign; 97 q.trim(); 98 r.trim(); 99 return { q, r / norm }; 100 } 101 102 friend bigint sqrt(const bigint &a1) { 103 bigint a = a1; 104 while (a.z.empty() || a.z.size() % 2 == 1) 105 a.z.push_back(0); 106 107 int n = a.z.size(); 108 109 int firstDigit = (int) ::sqrt((double)a.z[n - 1] * base + a.z[n - 2]); 110 int norm = base / (firstDigit + 1); 111 a *= norm; 112 a *= norm; 113 while (a.z.empty() || a.z.size() % 2 == 1) 114 a.z.push_back(0); 115 116 bigint r = (long long)a.z[n - 1] * base + a.z[n - 2]; 117 firstDigit = (int) ::sqrt((double)a.z[n - 1] * base + a.z[n - 2]); 118 int q = firstDigit; 119 bigint res; 120 121 for (int j = n / 2 - 1; j >= 0; j--) { 122 for (;; --q) { 123 bigint r1 = (r - (res * 2 * base + q) * q) * base * base + 124 (j > 0 ? (long long)a.z[2 * j - 1] * base + a.z[2 * j - 2] : 0); 125 if (r1 >= 0) { 126 r = r1; 127 break; 128 } 129 } 130 res *= base; 131 res += q; 132 133 if (j > 0) { 134 int d1 = res.z.size() + 2 < r.z.size() ? r.z[res.z.size() + 2] : 0; 135 int d2 = res.z.size() + 1 < r.z.size() ? r.z[res.z.size() + 1] : 0; 136 int d3 = res.z.size() < r.z.size() ? r.z[res.z.size()] : 0; 137 q = (int)(((long long)d1 * base * base + (long long)d2 * base + d3) / (firstDigit * 2)); 138 } 139 } 140 141 res.trim(); 142 return res / norm; 143 } 144 145 bigint operator/(const bigint &v) const { return divmod(*this, v).first; } 146 147 bigint operator%(const bigint &v) const { return divmod(*this, v).second; } 148 149 bigint &operator/=(int v) { 150 if (v < 0) sign = -sign, v = -v; 151 for (int i = (int)z.size() - 1, rem = 0; i >= 0; --i) { 152 long long cur = z[i] + rem * (long long)base; 153 z[i] = (int)(cur / v); 154 rem = (int)(cur % v); 155 } 156 trim(); 157 return *this; 158 } 159 160 bigint operator/(int v) const { return bigint(*this) /= v; } 161 162 int operator%(int v) const { 163 if (v < 0) v = -v; 164 int m = 0; 165 for (int i = (int)z.size() - 1; i >= 0; --i) 166 m = (int)((z[i] + m * (long long)base) % v); 167 return m * sign; 168 } 169 170 bigint &operator*=(const bigint &v) { return *this = *this * v; } 171 172 bigint &operator/=(const bigint &v) { return *this = *this / v; } 173 174 bool operator<(const bigint &v) const { 175 if (sign != v.sign) 176 return sign < v.sign; 177 if (z.size() != v.z.size()) 178 return z.size() * sign < v.z.size() * v.sign; 179 for (int i = (int)z.size() - 1; i >= 0; i--) 180 if (z[i] != v.z[i]) 181 return z[i] * sign < v.z[i] * sign; 182 return false; 183 } 184 185 bool operator>(const bigint &v) const { return v < *this; } 186 187 bool operator<=(const bigint &v) const { return !(v < *this); } 188 189 bool operator>=(const bigint &v) const { return !(*this < v); } 190 191 bool operator==(const bigint &v) const { return !(*this < v) && !(v < *this); } 192 193 bool operator!=(const bigint &v) const { return *this < v || v < *this; } 194 195 void trim() { 196 while (!z.empty() && z.back() == 0) z.pop_back(); 197 if (z.empty()) sign = 1; 198 } 199 200 bool isZero() const { return z.empty(); } 201 202 friend bigint operator-(bigint v) { 203 if (!v.z.empty()) v.sign = -v.sign; 204 return v; 205 } 206 207 bigint abs() const { 208 return sign == 1 ? *this : -*this; 209 } 210 211 long long longValue() const { 212 long long res = 0; 213 for (int i = (int)z.size() - 1; i >= 0; i--) 214 res = res * base + z[i]; 215 return res * sign; 216 } 217 218 friend bigint gcd(const bigint &a, const bigint &b) { 219 return b.isZero() ? a : gcd(b, a % b); 220 } 221 222 friend bigint lcm(const bigint &a, const bigint &b) { 223 return a / gcd(a, b) * b; 224 } 225 226 void read(const string &s) { 227 sign = 1; 228 z.clear(); 229 int pos = 0; 230 while (pos < s.size() && (s[pos] == ‘-‘ || s[pos] == ‘+‘)) { 231 if (s[pos] == ‘-‘) 232 sign = -sign; 233 ++pos; 234 } 235 for (int i = (int)s.size() - 1; i >= pos; i -= base_digits) { 236 int x = 0; 237 for (int j = max(pos, i - base_digits + 1); j <= i; j++) 238 x = x * 10 + s[j] - ‘0‘; 239 z.push_back(x); 240 } 241 trim(); 242 } 243 244 friend istream &operator>>(istream &stream, bigint &v) { 245 string s; 246 stream >> s; 247 v.read(s); 248 return stream; 249 } 250 251 friend ostream &operator<<(ostream &stream, const bigint &v) { 252 if (v.sign == -1) 253 stream << ‘-‘; 254 stream << (v.z.empty() ? 0 : v.z.back()); 255 for (int i = (int)v.z.size() - 2; i >= 0; --i) 256 stream << setw(base_digits) << setfill(‘0‘) << v.z[i]; 257 return stream; 258 } 259 260 static vector<int> convert_base(const vector<int> &a, int old_digits, int new_digits) { 261 vector<long long> p(max(old_digits, new_digits) + 1); 262 p[0] = 1; 263 for (int i = 1; i < p.size(); i++) 264 p[i] = p[i - 1] * 10; 265 vector<int> res; 266 long long cur = 0; 267 int cur_digits = 0; 268 for (int v : a) { 269 cur += v * p[cur_digits]; 270 cur_digits += old_digits; 271 while (cur_digits >= new_digits) { 272 res.push_back(int(cur % p[new_digits])); 273 cur /= p[new_digits]; 274 cur_digits -= new_digits; 275 } 276 } 277 res.push_back((int)cur); 278 while (!res.empty() && res.back() == 0) 279 res.pop_back(); 280 return res; 281 } 282 283 typedef vector<long long> vll; 284 285 static vll karatsubaMultiply(const vll &a, const vll &b) { 286 int n = a.size(); 287 vll res(n + n); 288 if (n <= 32) { 289 for (int i = 0; i < n; i++) 290 for (int j = 0; j < n; j++) 291 res[i + j] += a[i] * b[j]; 292 return res; 293 } 294 295 int k = n >> 1; 296 vll a1(a.begin(), a.begin() + k); 297 vll a2(a.begin() + k, a.end()); 298 vll b1(b.begin(), b.begin() + k); 299 vll b2(b.begin() + k, b.end()); 300 301 vll a1b1 = karatsubaMultiply(a1, b1); 302 vll a2b2 = karatsubaMultiply(a2, b2); 303 304 for (int i = 0; i < k; i++) 305 a2[i] += a1[i]; 306 for (int i = 0; i < k; i++) 307 b2[i] += b1[i]; 308 309 vll r = karatsubaMultiply(a2, b2); 310 for (int i = 0; i < a1b1.size(); i++) 311 r[i] -= a1b1[i]; 312 for (int i = 0; i < a2b2.size(); i++) 313 r[i] -= a2b2[i]; 314 315 for (int i = 0; i < r.size(); i++) 316 res[i + k] += r[i]; 317 for (int i = 0; i < a1b1.size(); i++) 318 res[i] += a1b1[i]; 319 for (int i = 0; i < a2b2.size(); i++) 320 res[i + n] += a2b2[i]; 321 return res; 322 } 323 324 bigint operator*(const bigint &v) const { 325 vector<int> a6 = convert_base(this->z, base_digits, 6); 326 vector<int> b6 = convert_base(v.z, base_digits, 6); 327 vll a(a6.begin(), a6.end()); 328 vll b(b6.begin(), b6.end()); 329 while (a.size() < b.size()) 330 a.push_back(0); 331 while (b.size() < a.size()) 332 b.push_back(0); 333 while (a.size() & (a.size() - 1)) 334 a.push_back(0), b.push_back(0); 335 vll c = karatsubaMultiply(a, b); 336 bigint res; 337 res.sign = sign * v.sign; 338 for (int i = 0, carry = 0; i < c.size(); i++) { 339 long long cur = c[i] + carry; 340 res.z.push_back((int)(cur % 1000000)); 341 carry = (int)(cur / 1000000); 342 } 343 res.z = convert_base(res.z, 6, base_digits); 344 res.trim(); 345 return res; 346 } 347 348 };
标签:stat cto pre ble 一个 air i++ span event
原文地址:https://www.cnblogs.com/feiyue-1779930274/p/11628128.html