Skip to content

Commit 3c08056

Browse files
committed
More inplace stuff
1 parent 2583069 commit 3c08056

File tree

4 files changed

+52
-36
lines changed

4 files changed

+52
-36
lines changed

cp-algo/math/poly.hpp

Lines changed: 45 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,25 @@ namespace cp_algo::math {
3333
poly_t operator + (poly_t const& t) const {return poly_t(*this) += t;}
3434
poly_t operator - (poly_t const& t) const {return poly_t(*this) -= t;}
3535

36-
poly_t mod_xk(size_t k) const {return poly::impl::mod_xk(*this, k);} // %= x^k
37-
poly_t mul_xk(size_t k) const {return poly::impl::mul_xk(*this, k);} // *= x^k
38-
poly_t div_xk(size_t k) const {return poly::impl::div_xk(*this, k);} // /= x^k
36+
poly_t& mod_xk_inplace(size_t k) {
37+
a.resize(std::min(size(a), k));
38+
normalize();
39+
return *this;
40+
}
41+
poly_t& mul_xk_inplace(size_t k) {
42+
a.insert(begin(a), k, T(0));
43+
normalize();
44+
return *this;
45+
}
46+
poly_t& div_xk_inplace(size_t k) {
47+
a.erase(begin(a), min(k, size(a)));
48+
normalize();
49+
return *this;
50+
}
51+
poly_t mod_xk(size_t k) const {return poly_t(*this).mod_xk_inplace(k);}
52+
poly_t mul_xk(size_t k) const {return poly_t(*this).mul_xk_inplace(k);}
53+
poly_t div_xk(size_t k) const {return poly_t(*this).div_xk_inplace(k);}
54+
3955
poly_t substr(size_t l, size_t k) const {return poly::impl::substr(*this, l, k);}
4056

4157
poly_t operator *= (const poly_t &t) {fft::mul(a, t.a); normalize(); return *this;}
@@ -135,17 +151,28 @@ namespace cp_algo::math {
135151
bool operator == (const poly_t &t) const {return a == t.a;}
136152
bool operator != (const poly_t &t) const {return a != t.a;}
137153

138-
poly_t deriv(int k = 1) const { // calculate derivative
154+
poly_t& deriv_inplace(int k = 1) {
139155
if(deg() + 1 < k) {
140-
return poly_t(T(0));
156+
return *this = poly_t{};
141157
}
142-
std::vector<T> res(deg() + 1 - k);
143158
for(int i = k; i <= deg(); i++) {
144-
res[i - k] = fact<T>(i) * rfact<T>(i - k) * a[i];
159+
a[i - k] = fact<T>(i) * rfact<T>(i - k) * a[i];
145160
}
146-
return res;
161+
a.resize(deg() + 1 - k);
162+
return *this;
163+
}
164+
poly_t deriv(int k = 1) const { // calculate derivative
165+
return poly_t(*this).deriv_inplace(k);
166+
}
167+
168+
poly_t& integr_inplace() {
169+
a.push_back(0);
170+
for(int i = deg() - 1; i >= 0; i--) {
171+
a[i + 1] = a[i] * small_inv<T>(i + 1);
172+
}
173+
a[0] = 0;
174+
return *this;
147175
}
148-
149176
poly_t integr() const { // calculate integral with C = 0
150177
std::vector<T> res(deg() + 2);
151178
for(int i = 0; i <= deg(); i++) {
@@ -165,9 +192,15 @@ namespace cp_algo::math {
165192
return res;
166193
}
167194

168-
poly_t log(size_t n) const { // calculate log p(x) mod x^n
195+
// calculate log p(x) mod x^n
196+
poly_t log_inplace(size_t n) {
169197
assert(a[0] == T(1));
170-
return (mod_xk(n).deriv() * inv(n)).mod_xk(n - 1).integr();
198+
auto t = mod_xk_inplace(n).inv(n);
199+
deriv_inplace();
200+
return (*this *= t).mod_xk_inplace(n - 1).integr_inplace();
201+
}
202+
poly_t log(size_t n) const {
203+
return poly_t(*this).log_inplace(n);
171204
}
172205

173206
poly_t exp(size_t n) const { // calculate exp p(x) mod x^n
@@ -585,8 +618,7 @@ namespace cp_algo::math {
585618

586619
// inverse series mod x^n
587620
poly_t& inv_inplace(size_t n) {
588-
poly::impl::inv_inplace(*this, n);
589-
return *this;
621+
return poly::impl::inv_inplace(*this, n);
590622
}
591623
poly_t inv(size_t n) const {
592624
return poly_t(*this).inv_inplace(n);

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

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -34,24 +34,6 @@ namespace cp_algo::math::poly::impl {
3434
normalize(p);
3535
return p;
3636
}
37-
auto mod_xk(auto const& p, size_t k) {
38-
return std::vector(begin(p.a), begin(p.a) + std::min(k, p.a.size()));
39-
}
40-
auto mul_xk(auto p, int k) {
41-
if(k < 0) {
42-
return p.div_xk(-k);
43-
}
44-
p.a.insert(begin(p.a), k, 0);
45-
normalize(p);
46-
return p;
47-
}
48-
template<typename poly>
49-
poly div_xk(poly const& p, int k) {
50-
if(k < 0) {
51-
return p.mul_xk(-k);
52-
}
53-
return std::vector(begin(p.a) + std::min<size_t>(k, p.a.size()), end(p.a));
54-
}
5537
auto substr(auto const& p, size_t l, size_t k) {
5638
return std::vector(
5739
begin(p.a) + std::min(l, p.a.size()),

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

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,11 @@ namespace cp_algo::math::poly::impl {
9191
).div_xk(2*q0.deg()).mod_xk(n);
9292
}
9393
template<typename poly>
94-
void inv_inplace(poly&& p, size_t n) {
94+
poly& inv_inplace(poly& p, size_t n) {
9595
using poly_t = std::decay_t<poly>;
9696
using base = poly_t::base;
9797
if(n == 1) {
98-
p = base(1) / p[0];
99-
return;
98+
return p = base(1) / p[0];
10099
}
101100
// Q(-x) = P0(x^2) + xP1(x^2)
102101
auto [q0, q1] = p.bisect(n);
@@ -107,7 +106,8 @@ namespace cp_algo::math::poly::impl {
107106
auto q1f = fft::dft<base>(q1.a, N);
108107

109108
// Q(x)*Q(-x) = Q0(x^2)^2 - x^2 Q1(x^2)^2
110-
auto qq = poly_t(q0f * q0f) - poly_t(q1f * q1f).mul_xk(1);
109+
auto qq = poly_t(q0f * q0f) - poly_t(q1f * q1f).mul_xk_inplace(1);
110+
111111
inv_inplace(qq, (n + 1) / 2);
112112
auto qqf = fft::dft<base>(qq.a, N);
113113

@@ -120,6 +120,8 @@ namespace cp_algo::math::poly::impl {
120120
p.a[i + 1] = -B[i / 2];
121121
}
122122
p.a.pop_back();
123+
p.normalize();
124+
return p;
123125
}
124126
}
125127
#endif // CP_ALGO_MATH_POLY_IMPL_DIV_HPP

verify/poly/log.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).log(n).print(n);
19+
polyn(a).log_inplace(n).print(n);
2020
}
2121

2222
signed main() {

0 commit comments

Comments
 (0)