Skip to content

Commit

Permalink
Merge pull request yosupo06#1117 from kzrnm/BurnikelZieglerBound
Browse files Browse the repository at this point in the history
Division Of (Hex) Big Integer のテストケース追加
  • Loading branch information
maspypy authored Mar 23, 2024
2 parents 61f0140 + d3176bf commit bffd3ee
Show file tree
Hide file tree
Showing 10 changed files with 265 additions and 55 deletions.
62 changes: 44 additions & 18 deletions math/addition_of_hex_big_integers/base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,7 @@ struct BigInteger

// A * B = (z2<<(2*shift)) + (z1<<shift) + z0

const size_t n = (asize) >> 1;
const size_t n = (asize + 1) >> 1;
if (bsize <= n)
{
// | A_hi | A_lo |
Expand Down Expand Up @@ -473,9 +473,9 @@ struct BigInteger
b + n, b_end,
c + n + n, c_end);

vector<uint32_t> a1(asize - n + 1);
vector<uint32_t> a1(n + 1);
vector<uint32_t> b1(n + 1);
vector<uint32_t> z1(asize + 2);
vector<uint32_t> z1(2 * n + 2);
_add(
a, a + n,
a + n, a_end,
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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<uint32_t> 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()))
Expand Down Expand Up @@ -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<uint32_t> yq = _mul(y, {q});
uint64_t q = rb / yb;
if (q > UINT32_MAX)
q = UINT32_MAX;

vector<uint32_t> yq = _mul(y, {(uint32_t)q});
// 真の商は q-2 以上 q+1 以下だが自信が無いので念のため while を回す
while (_lt(rv, yq))
q--, yq = _sub(yq, y);
Expand Down Expand Up @@ -958,12 +977,19 @@ struct BigInteger
}

static void _dump(const vector<uint32_t> &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;
}
};
Expand Down
2 changes: 1 addition & 1 deletion math/division_of_big_integers/base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdint>
#include <cmath>
#include <iostream>
#include <tuple>
#include <utility>
Expand Down
55 changes: 55 additions & 0 deletions math/division_of_big_integers/gen/burnikel_ziegler_bound.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
* |A| % |B| nearly equals to 0.
*/

#include <iostream>

#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<string> 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());
}
}
8 changes: 8 additions & 0 deletions math/division_of_big_integers/hash.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
3 changes: 3 additions & 0 deletions math/division_of_big_integers/info.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
62 changes: 44 additions & 18 deletions math/division_of_hex_big_integers/base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,7 @@ struct BigInteger

// A * B = (z2<<(2*shift)) + (z1<<shift) + z0

const size_t n = (asize) >> 1;
const size_t n = (asize + 1) >> 1;
if (bsize <= n)
{
// | A_hi | A_lo |
Expand Down Expand Up @@ -473,9 +473,9 @@ struct BigInteger
b + n, b_end,
c + n + n, c_end);

vector<uint32_t> a1(asize - n + 1);
vector<uint32_t> a1(n + 1);
vector<uint32_t> b1(n + 1);
vector<uint32_t> z1(asize + 2);
vector<uint32_t> z1(2 * n + 2);
_add(
a, a + n,
a + n, a_end,
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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<uint32_t> 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()))
Expand Down Expand Up @@ -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<uint32_t> yq = _mul(y, {q});
uint64_t q = rb / yb;
if (q > UINT32_MAX)
q = UINT32_MAX;

vector<uint32_t> yq = _mul(y, {(uint32_t)q});
// 真の商は q-2 以上 q+1 以下だが自信が無いので念のため while を回す
while (_lt(rv, yq))
q--, yq = _sub(yq, y);
Expand Down Expand Up @@ -958,12 +977,19 @@ struct BigInteger
}

static void _dump(const vector<uint32_t> &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;
}
};
Expand Down
55 changes: 55 additions & 0 deletions math/division_of_hex_big_integers/gen/burnikel_ziegler_bound.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
* |A| % |B| nearly equals to 0.
*/

#include <iostream>

#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<string> 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());
}
}
8 changes: 8 additions & 0 deletions math/division_of_hex_big_integers/hash.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
3 changes: 3 additions & 0 deletions math/division_of_hex_big_integers/info.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
Loading

0 comments on commit bffd3ee

Please sign in to comment.