From 65900061fc167b361231d02a89dbf20d3686f6a9 Mon Sep 17 00:00:00 2001 From: ZhuangYumin Date: Wed, 1 Nov 2023 14:10:43 +0800 Subject: [PATCH] upd: TimesByInt --- include/int2048.h | 5 +++-- src/int2048.cpp | 52 +++++++++++++++++++++++++++++++++++------------ tester/proc.cpp | 6 ++---- 3 files changed, 44 insertions(+), 19 deletions(-) diff --git a/include/int2048.h b/include/int2048.h index 3a50191..94164b9 100644 --- a/include/int2048.h +++ b/include/int2048.h @@ -48,7 +48,7 @@ root= 6 __int128_t QuickPow(__int128_t v, long long q); void NTTTransform(__int128_t *, int, bool); - + public: int2048(); int2048(long long); @@ -57,7 +57,7 @@ root= 6 int2048(int2048 &&) noexcept; ~int2048(); - + void UnsignedMultiplyByInt(int); void LeftMoveBy(int); void RightMoveBy(int); @@ -114,6 +114,7 @@ root= 6 friend bool operator<=(const int2048 &, const int2048 &); friend bool operator>=(const int2048 &, const int2048 &); }; +int2048 GetInv(const int2048 &,int); } // namespace sjtu #endif \ No newline at end of file diff --git a/src/int2048.cpp b/src/int2048.cpp index 5acc5f8..0fb459f 100644 --- a/src/int2048.cpp +++ b/src/int2048.cpp @@ -536,7 +536,33 @@ int2048 operator*(int2048 A, const int2048 &B) { A.Multiply(B); return std::move(A); } +void int2048::UnsignedMultiplyByInt(int v) { + if (v < 0) throw "UnsignedMultiplyByInt: v < 0"; + if (v == 0) { + *this = std::move(int2048(0)); + return; + } + if (v == 1) return; + int blocks = (this->num_length + int2048::kNum - 1) / int2048::kNum; + this->ClaimMem(this->num_length + int2048::kNum * 2); + blocks += 2; + long long c = 0; + for (int i = 0; i < blocks; i++) { + long long tmp = (long long)this->val[i] * v + c; + c = tmp / int2048::kStoreBase; + this->val[i] = tmp % int2048::kStoreBase; + } + this->num_length = blocks * int2048::kNum; + const static int kPow10[9] = {1, 10, 100, 1000, 10000, + 100000, 1000000, 10000000, 100000000}; + while (this->num_length > 1 && + this->val[(this->num_length - 1) / int2048::kNum] / + kPow10[(this->num_length - 1) % int2048::kNum] == + 0) + this->num_length--; +} +int2048 GetInv(const int2048 &, int) { ; } inline void UnsignedDivide(int2048 &A, const int2048 *pB) { int2048 B(*pB); int L1 = (A.num_length + int2048::kNum - 1) / int2048::kNum; @@ -545,15 +571,6 @@ inline void UnsignedDivide(int2048 &A, const int2048 *pB) { /** * reference: * https://github.com/lzyrapx/Competitive-Programming-Docs/blob/master/WC%E8%AE%B2%E8%AF%BE%E8%B5%84%E6%96%99/%E7%90%86%E6%80%A7%E6%84%89%E6%82%A6%E2%80%94%E2%80%94%E9%AB%98%E7%B2%BE%E5%BA%A6%E6%95%B0%E5%80%BC%E8%AE%A1%E7%AE%97%EF%BC%882012WC%EF%BC%89.pdf - * - * the algorithm is as follows: - * 1. if L2<=2, special process - * 2. Left move A and B, making 2*L2>=L1 - * 3. calculate [10^(2*n)/B] - * 1. define C_k=[10^(2k)/B_k] (B_k is the first k numbers of B) - * 2. then C_2k=2*C_k*10^k-[A*C_k^2/10^2k] - * 3. get accurate [10^(2*n)/B] by iteration - * 4. calculate [10^(2*n)/B]*A and ajust */ if (L2 <= 2) { long long b = B.val[0] + (long long)B.val[1] * int2048::kStoreBase; @@ -573,6 +590,10 @@ inline void UnsignedDivide(int2048 &A, const int2048 *pB) { A.num_length--; return; } + if (UnsignedCmp(A, *pB) < 0) { + A = std::move(int2048(0)); + return; + } if (2 * L2 < L1) { int delta = L1 - 2 * L2; A.LeftMoveBy(delta * int2048::kNum); @@ -583,10 +604,15 @@ inline void UnsignedDivide(int2048 &A, const int2048 *pB) { assert(L1 == (A.num_length + int2048::kNum - 1) / int2048::kNum); assert(L2 == (B.num_length + int2048::kNum - 1) / int2048::kNum); assert(2 * L2 >= L1); - int k = 2; - do { - /* code */ - } while (k * 2 <= L2); + int2048 res_hat = std::move(GetInv(B, L2)); + UnsignedMultiply(res_hat, &A); + res_hat.RightMoveBy(2 * L2 * int2048::kNum); + int2048 remain(A), tmp_B(B); + UnsignedMultiply(tmp_B, &res_hat); + UnsignedMinus(remain, &tmp_B); + for (int i = 8; i > 0; i >>= 1) { + tmp_B = B; + } } int2048 &int2048::Divide(const int2048 &B) { if (this == &B) { diff --git a/tester/proc.cpp b/tester/proc.cpp index bf633b3..8713d06 100644 --- a/tester/proc.cpp +++ b/tester/proc.cpp @@ -2,11 +2,9 @@ int main() { using namespace sjtu; - int2048 a("123456789"); + int2048 a("1234567871928347194791784918734981"); a.print(); puts(""); - a.LeftMoveBy(17); - a.print(); puts(""); - a.RightMoveBy(17); + a.UnsignedMultiplyByInt(2147483647); a.print(); puts(""); return 0; } \ No newline at end of file