Hi everyone!
Here's another collection of little tricks and general ideas that might make your life better (or maybe worse).
Evaluating polynomial modulo small prime $$$p$$$. Given a polynomial $$$q(x)$$$, you may evaluate it modulo $$$p$$$ in all possible arguments. To do this, compute $$$q(0)$$$ separately and use chirp Z-transform to compute $$$q(g^0), q(g^1), \dots, q(g^{p-2})$$$, where $$$g$$$ is a primitive root modulo $$$p$$$.
Generalized Euler theorem. Let $$$a$$$ be a number, not necessarily co-prime with $$$m$$$, and $$$k > \log_2 m$$$. Then
where $$$\phi(m)$$$ is Euler's totient. This follows from the Chinese remainder theorem, as it trivially holds for $$$m=p^d$$$.
Range add/range sum on a plane. Fenwick tree, generally, allows for range sum/point add queries.
Let $$$s_{xy}$$$ be a sum on $$$[1,x] \times [1,y]$$$. If we add $$$c$$$ on $$$[a, +\infty) \times [b, +\infty)$$$, the sum $$$s_{xy}$$$ would change as
for $$$x \geq a$$$ and $$$y \geq b$$$. To track these changes, we may represent $$$s_{xy}$$$ as
which allows us to split the addition of $$$c$$$ on $$$[a,+\infty) \times [b,+\infty)$$$ into additions in $$$(a;b)$$$:
The solution generalizes 1-dimensional Fenwick range updates idea from Petr blog from 2013.
DP on convex subsets.
Assume you want to compute something related to convex subsets of a given set of points in 2D space.
This can be done with dynamic programming, which generally goes as follows:
- Iterate over possible bottom left point $$$O$$$ of the convex subset;
- Ignore points below it and sort points above it by angle that they form with $$$O$$$;
- Iterate over possible point $$$B$$$ to be the "last" in the convex subset. It may only be preceded by a point that was sorted before it and succeeded by a points that was sorted after it when the points were sorted around $$$O$$$;
- Sort considered points around $$$B$$$, separately in "yellow" and "green" areas (see picture);
- Iterate over possible point $$$C$$$ which will succeed $$$B$$$ in the convex subset;
- Set of points that may precede $$$B$$$ with a next point $$$C$$$ form a contiguous prefix of points before $$$B$$$;
- The second pointer $$$A$$$ to the end of the prefix is maintained;
- Eventually, for every $$$B$$$, all valid pairs of $$$A$$$ and $$$C$$$ are iterated with two pointers.
This allows to consider in $$$O(n^3)$$$ all the convex subsets of a given set of points, assuming that sorting around every point $$$B$$$ was computed beforehand in $$$O(n^2 \log n)$$$ and is now used to avoid actual second sorting of points around $$$B$$$.
Knapsack on segments. You're given $$$a_1, \dots, a_n$$$ and need to answer $$$q$$$ queries. Each query is whether $$$a_l, a_{l+1}, \dots, a_r$$$ has a subset sum $$$w$$$. This can be done with dynamic programming $$$L[r][w]$$$ being the right-most $$$l$$$ such that $$$a_l, \dots, a_r$$$ has a subset with sum $$$w$$$: