diff --git a/math/addition_of_hex_big_integers/base.hpp b/math/addition_of_hex_big_integers/base.hpp index f838e39ee..cb56f52cf 100644 --- a/math/addition_of_hex_big_integers/base.hpp +++ b/math/addition_of_hex_big_integers/base.hpp @@ -435,7 +435,7 @@ struct BigInteger // A * B = (z2<<(2*shift)) + (z1<> 1; + const size_t n = (asize + 1) >> 1; if (bsize <= n) { // | A_hi | A_lo | @@ -473,9 +473,9 @@ struct BigInteger b + n, b_end, c + n + n, c_end); - vector a1(asize - n + 1); + vector a1(n + 1); vector b1(n + 1); - vector z1(asize + 2); + vector z1(2 * n + 2); _add( a, a + n, a + n, a_end, @@ -642,6 +642,7 @@ struct BigInteger assert(asize == 2 * n); assert(qsize == n); assert(rsize == n + 1); + assert(_lt(a + n, a_end, b, b_end)); if (n % 2 != 0 || n <= _div_naive_th) { @@ -685,19 +686,34 @@ struct BigInteger assert(bsize == 2 * n); assert(qsize == n); assert(rsize == 2 * n + 1); - assert(_lt(a + n + n, a_end, b + n, b_end)); - - _divmod_d2n1n( - a + n, a_end, - b + n, b_end, - quo, quo_end, - rem + n, rem_end); + assert(_lt(a + n, a_end, b, b_end)); vector d(2 * n); - _mul( - quo, quo_end, - b, b + n, - d.begin(), d.end()); + + if (_lt(a + n + n, a_end, b + n, b_end)) + { + _divmod_d2n1n( + a + n, a_end, + b + n, b_end, + quo, quo_end, + rem + n, rem_end); + _mul( + quo, quo_end, + b, b + n, + d.begin(), d.end()); + } + else + { + fill(quo, quo_end, UINT32_MAX); + + _add( + a + n, a + n + n, + b + n, b_end, + rem + n, rem_end); + copy(b, b + n, d.begin() + n); + _sub(d.begin(), d.end(), b, b + n); + } + copy(a, a + n, rem); while (_lt(rem, rem_end, d.cbegin(), d.cend())) @@ -783,8 +799,11 @@ struct BigInteger uint64_t rb = rv[rv.size() - 1]; rb <<= 32; rb |= rv[rv.size() - 2]; - uint32_t q = rb / yb; - vector yq = _mul(y, {q}); + uint64_t q = rb / yb; + if (q > UINT32_MAX) + q = UINT32_MAX; + + vector yq = _mul(y, {(uint32_t)q}); // 真の商は q-2 以上 q+1 以下だが自信が無いので念のため while を回す while (_lt(rv, yq)) q--, yq = _sub(yq, y); @@ -958,12 +977,19 @@ struct BigInteger } static void _dump(const vector &a, string s = "") + { + _dump(a.cbegin(), a.cend(), s); + } + + static void _dump(citer a, citer a_end, string s = "") { if (!s.empty()) cerr << s << " : "; cerr << "{ "; - for (int i = 0; i < (int)a.size(); i++) - cerr << a[i] << ", "; + for (citer it = a; it < a_end; ++it) + { + cerr << *it << ", "; + } cerr << "}" << endl; } }; diff --git a/math/division_of_big_integers/base.hpp b/math/division_of_big_integers/base.hpp index 5ecf3ff58..380591959 100644 --- a/math/division_of_big_integers/base.hpp +++ b/math/division_of_big_integers/base.hpp @@ -2,8 +2,8 @@ #include #include -#include #include +#include #include #include #include diff --git a/math/division_of_big_integers/gen/burnikel_ziegler_bound.cpp b/math/division_of_big_integers/gen/burnikel_ziegler_bound.cpp new file mode 100644 index 000000000..28ddd9039 --- /dev/null +++ b/math/division_of_big_integers/gen/burnikel_ziegler_bound.cpp @@ -0,0 +1,55 @@ +/** + * |A| % |B| nearly equals to 0. + */ + +#include + +#include "../base.hpp" +#include "../params.h" +#include "random.h" +using namespace std; +using ll = long long; + +int main(int, char *argv[]) +{ + ll seed = atoll(argv[1]); + + bigint base; + if (seed % 4 == 0) + base = 10; + else if (seed % 4 == 1) + base = 1000000000; + else if (seed % 4 == 2) + base = 2; + else if (seed % 4 == 3) + base = 1LL << 32; + + int lsum = 0; + vector A, B; + bigint bb = base; + + for (size_t i = 1;; i++) + { + bigint quotient = 2 * bb * bb - 1; + bigint remainder = (bb - 1) * bb; + bigint y = remainder + 1; + bigint x = quotient * y + remainder; + + string sa = x.to_string(); + string sb = y.to_string(); + + lsum += sa.size() + sb.size(); + if (lsum > SUM_OF_CHARACTER_LENGTH) + break; + A.push_back(sa); + B.push_back(sb); + + bb *= base; + } + + printf("%d\n", (int)A.size()); + for (int i = 0; i < (int)A.size(); i++) + { + printf("%s %s\n", A[i].c_str(), B[i].c_str()); + } +} \ No newline at end of file diff --git a/math/division_of_big_integers/hash.json b/math/division_of_big_integers/hash.json index df36cec54..452dc177b 100644 --- a/math/division_of_big_integers/hash.json +++ b/math/division_of_big_integers/hash.json @@ -5,6 +5,14 @@ "a_max_b_random_01.out": "96ffc89918498b6f42fe223369fc30331d81c6b453d726d25e31e38a6d21e580", "a_max_b_random_02.in": "2bc10166cf5d82219562fe281aac5a6a751bdd55db5903c25c298fd18d4c4701", "a_max_b_random_02.out": "987c4acc5a419bca12d573a92667efe9016cbacd66f2862fd57b8483b1676fe8", + "burnikel_ziegler_bound_00.in": "4a73745f27eb3daac4aaa53a76ddf12b1c63d3da8bfb9a9c1e36843eba2dad5a", + "burnikel_ziegler_bound_00.out": "bd6a7ccd9f9dba2235096dd221ae4d81aed4d175bc54267eef22cee1a5b276c0", + "burnikel_ziegler_bound_01.in": "8d77bbb7ec6c7189db5ede02cc0a33ec1a894f8ac9a3b17c967b34661a380593", + "burnikel_ziegler_bound_01.out": "196018d8dbc217e9a3d2ceb2d16c8320017adca53a1ca3c781a517d2931a8283", + "burnikel_ziegler_bound_02.in": "ba629f205c4bf4383ee931a214fa56c007fd4d6198a33f5d64a2523b4a030bfc", + "burnikel_ziegler_bound_02.out": "0ca63971203f72b3f411abaa9cfc3b71f706b810bc2e8d3f7d28991ab39d0c2c", + "burnikel_ziegler_bound_03.in": "4a3893a860cee2b90b6bca663a68874b93b1fdca57aa320d788d8386491dbbba", + "burnikel_ziegler_bound_03.out": "c4d74880bceacbf4e932bb45ec4dbf58a6b6ccfcecace3c5df7e0db11de81afb", "example_00.in": "20ec2e6583200ccb191892fa2d56d406b38c49f286b68f398da10102644ef5df", "example_00.out": "e6832e88bcccbde103970c8f1ad0ff1e2869a21a22a026b72db0d6c12772e9a1", "large_00.in": "61e72c8892bb934813e31d56d674c3ee5fb363ee79fce1909a57e5048a0b7611", diff --git a/math/division_of_big_integers/info.toml b/math/division_of_big_integers/info.toml index f3f6c07ac..67ef3cc4b 100644 --- a/math/division_of_big_integers/info.toml +++ b/math/division_of_big_integers/info.toml @@ -26,6 +26,9 @@ forum = "https://github.com/yosupo06/library-checker-problems/issues/941" [[tests]] name = "length_ratio_integer.cpp" number = 6 +[[tests]] + name = "burnikel_ziegler_bound.cpp" + number = 4 [params] T_MAX = 2000000 diff --git a/math/division_of_hex_big_integers/base.hpp b/math/division_of_hex_big_integers/base.hpp index f838e39ee..cb56f52cf 100644 --- a/math/division_of_hex_big_integers/base.hpp +++ b/math/division_of_hex_big_integers/base.hpp @@ -435,7 +435,7 @@ struct BigInteger // A * B = (z2<<(2*shift)) + (z1<> 1; + const size_t n = (asize + 1) >> 1; if (bsize <= n) { // | A_hi | A_lo | @@ -473,9 +473,9 @@ struct BigInteger b + n, b_end, c + n + n, c_end); - vector a1(asize - n + 1); + vector a1(n + 1); vector b1(n + 1); - vector z1(asize + 2); + vector z1(2 * n + 2); _add( a, a + n, a + n, a_end, @@ -642,6 +642,7 @@ struct BigInteger assert(asize == 2 * n); assert(qsize == n); assert(rsize == n + 1); + assert(_lt(a + n, a_end, b, b_end)); if (n % 2 != 0 || n <= _div_naive_th) { @@ -685,19 +686,34 @@ struct BigInteger assert(bsize == 2 * n); assert(qsize == n); assert(rsize == 2 * n + 1); - assert(_lt(a + n + n, a_end, b + n, b_end)); - - _divmod_d2n1n( - a + n, a_end, - b + n, b_end, - quo, quo_end, - rem + n, rem_end); + assert(_lt(a + n, a_end, b, b_end)); vector d(2 * n); - _mul( - quo, quo_end, - b, b + n, - d.begin(), d.end()); + + if (_lt(a + n + n, a_end, b + n, b_end)) + { + _divmod_d2n1n( + a + n, a_end, + b + n, b_end, + quo, quo_end, + rem + n, rem_end); + _mul( + quo, quo_end, + b, b + n, + d.begin(), d.end()); + } + else + { + fill(quo, quo_end, UINT32_MAX); + + _add( + a + n, a + n + n, + b + n, b_end, + rem + n, rem_end); + copy(b, b + n, d.begin() + n); + _sub(d.begin(), d.end(), b, b + n); + } + copy(a, a + n, rem); while (_lt(rem, rem_end, d.cbegin(), d.cend())) @@ -783,8 +799,11 @@ struct BigInteger uint64_t rb = rv[rv.size() - 1]; rb <<= 32; rb |= rv[rv.size() - 2]; - uint32_t q = rb / yb; - vector yq = _mul(y, {q}); + uint64_t q = rb / yb; + if (q > UINT32_MAX) + q = UINT32_MAX; + + vector yq = _mul(y, {(uint32_t)q}); // 真の商は q-2 以上 q+1 以下だが自信が無いので念のため while を回す while (_lt(rv, yq)) q--, yq = _sub(yq, y); @@ -958,12 +977,19 @@ struct BigInteger } static void _dump(const vector &a, string s = "") + { + _dump(a.cbegin(), a.cend(), s); + } + + static void _dump(citer a, citer a_end, string s = "") { if (!s.empty()) cerr << s << " : "; cerr << "{ "; - for (int i = 0; i < (int)a.size(); i++) - cerr << a[i] << ", "; + for (citer it = a; it < a_end; ++it) + { + cerr << *it << ", "; + } cerr << "}" << endl; } }; diff --git a/math/division_of_hex_big_integers/gen/burnikel_ziegler_bound.cpp b/math/division_of_hex_big_integers/gen/burnikel_ziegler_bound.cpp new file mode 100644 index 000000000..ef1df9c54 --- /dev/null +++ b/math/division_of_hex_big_integers/gen/burnikel_ziegler_bound.cpp @@ -0,0 +1,55 @@ +/** + * |A| % |B| nearly equals to 0. + */ + +#include + +#include "../base.hpp" +#include "../params.h" +#include "random.h" +using namespace std; +using ll = long long; + +int main(int, char *argv[]) +{ + ll seed = atoll(argv[1]); + + bigint base; + if (seed % 4 == 0) + base = 10; + else if (seed % 4 == 1) + base = 1000000000; + else if (seed % 4 == 2) + base = 2; + else if (seed % 4 == 3) + base = 1uLL << 32; + + int lsum = 0; + vector A, B; + bigint bb = base; + + for (size_t i = 1;; i++) + { + bigint quotient = 2 * bb * bb - 1; + bigint remainder = (bb - 1) * bb; + bigint y = remainder + 1; + bigint x = quotient * y + remainder; + + string sa = x.to_string(); + string sb = y.to_string(); + + lsum += sa.size() + sb.size(); + if (lsum > SUM_OF_CHARACTER_LENGTH) + break; + A.push_back(sa); + B.push_back(sb); + + bb *= base; + } + + printf("%d\n", (int)A.size()); + for (int i = 0; i < (int)A.size(); i++) + { + printf("%s %s\n", A[i].c_str(), B[i].c_str()); + } +} \ No newline at end of file diff --git a/math/division_of_hex_big_integers/hash.json b/math/division_of_hex_big_integers/hash.json index a377acc56..9225cb019 100644 --- a/math/division_of_hex_big_integers/hash.json +++ b/math/division_of_hex_big_integers/hash.json @@ -5,6 +5,14 @@ "a_max_b_random_01.out": "3a2ae3457d9954b3dc2b837c8e4ca441a560e1262abace333fa045b672a7693b", "a_max_b_random_02.in": "bfd6e345cff6141afe8833ccc95fb0d2e7803e231367cdba85e348357cada13c", "a_max_b_random_02.out": "fdff2060f1dbad78babf1279fd33694e129a8ad46486160c767b969d8266c5a6", + "burnikel_ziegler_bound_00.in": "8bd68449153f8b23a400427408826d56ed040ae80b3101854fb5f3519986f5d3", + "burnikel_ziegler_bound_00.out": "85edea1e01307c385075d97612f63f0cc47036a9ca3e8d5b7355ddaa4d13f975", + "burnikel_ziegler_bound_01.in": "3195baf0ff1e0208c2909864505b8c7ac09d0a9736e78723d56fb025402ac4a8", + "burnikel_ziegler_bound_01.out": "189dee73cc1df07872102d19698bc5367e615fd7de66ed6723de0a3efc503dcd", + "burnikel_ziegler_bound_02.in": "0ad8e52122e27bd771a5d347929e95514fa0321f33f258bf1c9913311272eb9b", + "burnikel_ziegler_bound_02.out": "1e12d0c137e3804e60e204388abf2ca626b57fdfddca9e63cb8b1b7e369cdd7b", + "burnikel_ziegler_bound_03.in": "cc95078f5cb233a26ce6c83345e64340cf6a3cddec71cc8bcd6e99ce9c3914c4", + "burnikel_ziegler_bound_03.out": "a661be73fdc70fc3b610988bd5e854b4316a9e69b75cc2df8e964c9a9c8e2a61", "example_00.in": "f734364905adda25d4cb9ec9761f3e02675d7ffd221e5ca41a85bba1acb82e85", "example_00.out": "b591db1aae9bc3890ce0539994259982cf1964d8fcdbfd0d657fd8c37f9cc8d0", "large_00.in": "17fd92b0e66bd94798509e0bc7de37c1a837ed3013fcef22a7e6c868a969b5c0", diff --git a/math/division_of_hex_big_integers/info.toml b/math/division_of_hex_big_integers/info.toml index 7075b45a1..7a1189804 100644 --- a/math/division_of_hex_big_integers/info.toml +++ b/math/division_of_hex_big_integers/info.toml @@ -29,6 +29,9 @@ forum = "https://github.com/yosupo06/library-checker-problems/issues/1101" [[tests]] name = "length_ratio_integer.cpp" number = 6 +[[tests]] + name = "burnikel_ziegler_bound.cpp" + number = 4 [[solutions]] name = "correct.py" diff --git a/math/multiplication_of_hex_big_integers/base.hpp b/math/multiplication_of_hex_big_integers/base.hpp index f838e39ee..cb56f52cf 100644 --- a/math/multiplication_of_hex_big_integers/base.hpp +++ b/math/multiplication_of_hex_big_integers/base.hpp @@ -435,7 +435,7 @@ struct BigInteger // A * B = (z2<<(2*shift)) + (z1<> 1; + const size_t n = (asize + 1) >> 1; if (bsize <= n) { // | A_hi | A_lo | @@ -473,9 +473,9 @@ struct BigInteger b + n, b_end, c + n + n, c_end); - vector a1(asize - n + 1); + vector a1(n + 1); vector b1(n + 1); - vector z1(asize + 2); + vector z1(2 * n + 2); _add( a, a + n, a + n, a_end, @@ -642,6 +642,7 @@ struct BigInteger assert(asize == 2 * n); assert(qsize == n); assert(rsize == n + 1); + assert(_lt(a + n, a_end, b, b_end)); if (n % 2 != 0 || n <= _div_naive_th) { @@ -685,19 +686,34 @@ struct BigInteger assert(bsize == 2 * n); assert(qsize == n); assert(rsize == 2 * n + 1); - assert(_lt(a + n + n, a_end, b + n, b_end)); - - _divmod_d2n1n( - a + n, a_end, - b + n, b_end, - quo, quo_end, - rem + n, rem_end); + assert(_lt(a + n, a_end, b, b_end)); vector d(2 * n); - _mul( - quo, quo_end, - b, b + n, - d.begin(), d.end()); + + if (_lt(a + n + n, a_end, b + n, b_end)) + { + _divmod_d2n1n( + a + n, a_end, + b + n, b_end, + quo, quo_end, + rem + n, rem_end); + _mul( + quo, quo_end, + b, b + n, + d.begin(), d.end()); + } + else + { + fill(quo, quo_end, UINT32_MAX); + + _add( + a + n, a + n + n, + b + n, b_end, + rem + n, rem_end); + copy(b, b + n, d.begin() + n); + _sub(d.begin(), d.end(), b, b + n); + } + copy(a, a + n, rem); while (_lt(rem, rem_end, d.cbegin(), d.cend())) @@ -783,8 +799,11 @@ struct BigInteger uint64_t rb = rv[rv.size() - 1]; rb <<= 32; rb |= rv[rv.size() - 2]; - uint32_t q = rb / yb; - vector yq = _mul(y, {q}); + uint64_t q = rb / yb; + if (q > UINT32_MAX) + q = UINT32_MAX; + + vector yq = _mul(y, {(uint32_t)q}); // 真の商は q-2 以上 q+1 以下だが自信が無いので念のため while を回す while (_lt(rv, yq)) q--, yq = _sub(yq, y); @@ -958,12 +977,19 @@ struct BigInteger } static void _dump(const vector &a, string s = "") + { + _dump(a.cbegin(), a.cend(), s); + } + + static void _dump(citer a, citer a_end, string s = "") { if (!s.empty()) cerr << s << " : "; cerr << "{ "; - for (int i = 0; i < (int)a.size(); i++) - cerr << a[i] << ", "; + for (citer it = a; it < a_end; ++it) + { + cerr << *it << ", "; + } cerr << "}" << endl; } };