Skip to content

Commit dfebb6c

Browse files
committed
Improve inv
1 parent 93c1f88 commit dfebb6c

File tree

4 files changed

+29
-16
lines changed

4 files changed

+29
-16
lines changed

cp-algo/math/fft.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <cassert>
88
#include <ranges>
99
#include <vector>
10+
#include <deque>
1011
#include <bit>
1112

1213
namespace cp_algo::math::fft {
@@ -249,8 +250,8 @@ namespace cp_algo::math::fft {
249250
void mul(auto &&B, auto& res, size_t k) {
250251
mul(B.A, B.B, res, k);
251252
}
252-
std::vector<base> operator *= (auto &&B) {
253-
std::vector<base> res(2 * A.size());
253+
std::deque<base> operator *= (auto &&B) {
254+
std::deque<base> res(2 * A.size());
254255
mul(B.A, B.B, res, size(res));
255256
return res;
256257
}

cp-algo/math/poly.hpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,7 @@ namespace cp_algo::math {
538538
}
539539

540540
poly_t x2() { // P(x) -> P(x^2)
541-
std::vector<T> res(2 * a.size());
541+
std::deque<T> res(2 * a.size());
542542
for(size_t i = 0; i < a.size(); i++) {
543543
res[2 * i] = a[i];
544544
}
@@ -583,8 +583,12 @@ namespace cp_algo::math {
583583
}
584584

585585
// inverse series mod x^n
586+
poly_t& inv_inplace(size_t n) {
587+
poly::impl::inv_inplace(*this, n);
588+
return *this;
589+
}
586590
poly_t inv(size_t n) const {
587-
return poly::impl::inv(*this, n);
591+
return poly_t(*this).inv_inplace(n);
588592
}
589593
// [x^k]..[x^{k+n-1}] of inv()
590594
// supports negative k if k+n >= 0

cp-algo/math/poly/impl/div.hpp

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "../../fft.hpp"
44
#include "../../common.hpp"
55
#include <cassert>
6+
#include <deque>
67
// operations related to polynomial division
78
namespace cp_algo::math::poly::impl {
89
auto divmod_slow(auto const& p, auto const& q) {
@@ -90,27 +91,34 @@ namespace cp_algo::math::poly::impl {
9091
).div_xk(2*q0.deg()).mod_xk(n);
9192
}
9293
template<typename poly>
93-
poly inv(poly const& p, size_t n) {
94+
void inv_inplace(poly&& p, size_t n) {
95+
using poly_t = std::decay_t<poly>;
96+
using base = poly_t::base;
9497
if(n == 1) {
95-
return poly(1) / p[0];
98+
p = base(1) / p[0];
99+
return;
96100
}
97101
// Q(-x) = P0(x^2) + xP1(x^2)
98102
auto [q0, q1] = p.bisect(n);
99-
q1 *= -1;
100103

101104
int N = fft::com_size((n + 1) / 2, (n + 1) / 2);
102105

103-
auto q0f = fft::dft<typename poly::base>(q0.a, N);
104-
auto q1f = fft::dft<typename poly::base>(q1.a, N);
106+
auto q0f = fft::dft<base>(q0.a, N);
107+
auto q1f = fft::dft<base>(q1.a, N);
105108

106109
// Q(x)*Q(-x) = Q0(x^2)^2 - x^2 Q1(x^2)^2
107-
auto qqf = fft::dft<typename poly::base>(inv(
108-
poly(q0f * q0f) - poly(q1f * q1f).mul_xk(1)
109-
, (n + 1) / 2).a, N);
110+
auto qq = poly_t(q0f * q0f) - poly_t(q1f * q1f).mul_xk(1);
111+
inv_inplace(qq, (n + 1) / 2);
112+
auto qqf = fft::dft<base>(qq.a, N);
110113

111-
return (
112-
poly(q0f * qqf).x2() + poly(q1f * qqf).x2().mul_xk(1)
113-
).mod_xk(n);
114+
auto A = q0f * qqf;
115+
auto B = q1f * qqf;
116+
p.a.resize(n + 1);
117+
for(size_t i = 0; i < n; i += 2) {
118+
p.a[i] = A[i / 2];
119+
p.a[i + 1] = -B[i / 2];
120+
}
121+
p.a.pop_back();
114122
}
115123
}
116124
#endif // CP_ALGO_MATH_POLY_IMPL_DIV_HPP

verify/poly/inv.test.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ void solve() {
1616
cin >> n;
1717
vector<base> a(n);
1818
copy_n(istream_iterator<base>(cin), n, begin(a));
19-
polyn(a).inv(n).print(n);
19+
polyn(a).inv_inplace(n).print(n);
2020
}
2121

2222
signed main() {

0 commit comments

Comments
 (0)