@@ -112,11 +112,47 @@ namespace cp_algo::math {
112112 }
113113 };
114114
115+ template <base_v base>
116+ auto divmod_fast (bigint<base> const & a, int64_t b) {
117+ // Optimized divmod for small divisors that fit in int64_t
118+ if (b == 0 ) {
119+ assert (false && " Division by zero" );
120+ }
121+ bool neg_a = a.negative ;
122+ bool neg_b = b < 0 ;
123+ b = std::abs (b);
124+
125+ bigint<base> quotient;
126+ uint64_t remainder = 0 ;
127+
128+ auto n = ssize (a.digits );
129+ for (auto i = n - 1 ; i >= 0 ; i--) {
130+ __uint128_t val = (__uint128_t )remainder * bigint<base>::Base + a.digits [i];
131+ uint64_t q = uint64_t (val / b);
132+ remainder = uint64_t (val % b);
133+ quotient.digits .push_back (q);
134+ }
135+ std::ranges::reverse (quotient.digits );
136+ quotient.negative = (neg_a ^ neg_b);
137+ quotient.normalize ();
138+
139+ bigint<base> rem{int64_t (remainder)};
140+ rem.negative = neg_a;
141+
142+ return std::pair{quotient, rem};
143+ }
144+
115145 template <base_v base>
116146 auto divmod (bigint<base> const & a, bigint<base> const & b) {
117147 if (a < b) {
118148 return std::pair{bigint<base>(0 ), a};
119149 }
150+ // Use fast path if b fits in int64_t
151+ if (size (b.digits ) == 1 ) {
152+ int64_t b_val = b.negative ? -int64_t (b.digits [0 ]) : int64_t (b.digits [0 ]);
153+ return divmod_fast (a, b_val);
154+ }
155+ // General case using decimal arithmetic
120156 auto A = decimal<base>(a);
121157 auto B = decimal<base>(b);
122158 auto d = (A * B.inv (A.magnitude ())).trunc ();
0 commit comments