summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGloria Mundi <gloria@gloria-mundi.eu>2025-01-18 03:05:17 +0100
committerGloria Mundi <gloria@gloria-mundi.eu>2025-01-18 03:08:45 +0100
commit52ba871e0de9399f77da4b5b0d2c33a2dd6eb6a1 (patch)
tree493152c57313f651cae92f88b6f24af2ede1b6d6
parent69c98b39106cc2776f6a4983e548338ac24b5e84 (diff)
changes to bitwise convolutions
- modify or/and transform to remove unnecessary reversal - or transform is now sum over subsets, add note about this - remove old sum over subsets DP
-rw-r--r--content/math/math.tex6
-rw-r--r--content/math/transforms/andTransform.cpp2
-rw-r--r--content/math/transforms/bitwiseTransforms.cpp4
-rw-r--r--content/math/transforms/orTransform.cpp2
-rw-r--r--content/other/other.tex5
-rw-r--r--content/other/sos.cpp6
-rw-r--r--test/other/sos.cpp50
7 files changed, 10 insertions, 65 deletions
diff --git a/content/math/math.tex b/content/math/math.tex
index d59da54..fdf7081 100644
--- a/content/math/math.tex
+++ b/content/math/math.tex
@@ -321,6 +321,7 @@ sich alle Lösungen von $x^2-ny^2=c$ berechnen durch:
\end{algorithm}
\begin{algorithm}{Polynome, FFT, NTT \& andere Transformationen}
+ \label{fft}
Multipliziert Polynome $A$ und $B$.
\begin{itemize}
\item $\deg(A \cdot B) = \deg(A) + \deg(B)$
@@ -328,14 +329,15 @@ sich alle Lösungen von $x^2-ny^2=c$ berechnen durch:
$\deg(A \cdot B) + 1$ haben.
Größe muss eine Zweierpotenz sein.
\item Für ganzzahlige Koeffizienten: \code{(ll)round(real(a[i]))}
- \item \emph{xor}, \emph{or} und \emph{and} Transform funktioniert auch mit \code{double} oder modulo einer Primzahl $p$ falls $p \geq 2^{\texttt{bits}}$
+ \item \emph{or} Transform berechnet sum over subsets
+ $\rightarrow$ inverse für inclusion/exclusion
\end{itemize}
%\sourcecode{math/fft.cpp}
%\sourcecode{math/ntt.cpp}
\sourcecode{math/transforms/fft.cpp}
\sourcecode{math/transforms/ntt.cpp}
\sourcecode{math/transforms/bitwiseTransforms.cpp}
- Multiplikation mit 2 transforms statt 3: (nur benutzten wenn nötig!)
+ Multiplikation mit 2 Transforms statt 3: (nur benutzen wenn nötig!)
\sourcecode{math/transforms/fftMul.cpp}
\end{algorithm}
diff --git a/content/math/transforms/andTransform.cpp b/content/math/transforms/andTransform.cpp
index 1e9cfc0..9e40c74 100644
--- a/content/math/transforms/andTransform.cpp
+++ b/content/math/transforms/andTransform.cpp
@@ -4,5 +4,5 @@ void fft(vector<ll>& a, bool inv = false) {
for (int i = 0; i < n; i += 2 * s) {
for (int j = i; j < i + s; j++) {
ll& u = a[j], &v = a[j + s];
- tie(u, v) = inv ? pair(v - u, u) : pair(v, u + v);
+ tie(u, v) = inv ? pair(u - v, v) : pair(u + v, v);
}}}}
diff --git a/content/math/transforms/bitwiseTransforms.cpp b/content/math/transforms/bitwiseTransforms.cpp
index b98ea94..17f3163 100644
--- a/content/math/transforms/bitwiseTransforms.cpp
+++ b/content/math/transforms/bitwiseTransforms.cpp
@@ -4,8 +4,8 @@ void bitwiseConv(vector<ll>& a, bool inv = false) {
for (int i = 0; i < n; i += 2 * s) {
for (int j = i; j < i + s; j++) {
ll& u = a[j], &v = a[j + s];
- tie(u, v) = inv ? pair(v - u, u) : pair(v, u + v); // AND
- //tie(u, v) = inv ? pair(v, u - v) : pair(u + v, u); //OR
+ tie(u, v) = inv ? pair(u - v, v) : pair(u + v, v); // AND
+ //tie(u, v) = inv ? pair(u, v - u) : pair(u, v + u); //OR
//tie(u, v) = pair(u + v, u - v); // XOR
}}}
//if (inv) for (ll& x : a) x /= n; // XOR (careful with MOD)
diff --git a/content/math/transforms/orTransform.cpp b/content/math/transforms/orTransform.cpp
index d0122bf..6503a68 100644
--- a/content/math/transforms/orTransform.cpp
+++ b/content/math/transforms/orTransform.cpp
@@ -4,5 +4,5 @@ void fft(vector<ll>& a, bool inv = false) {
for (int i = 0; i < n; i += 2 * s) {
for (int j = i; j < i + s; j++) {
ll& u = a[j], &v = a[j + s];
- tie(u, v) = inv ? pair(v, u - v) : pair(u + v, u);
+ tie(u, v) = inv ? pair(u, v - u) : pair(u, v + u);
}}}}
diff --git a/content/other/other.tex b/content/other/other.tex
index 2519427..8896962 100644
--- a/content/other/other.tex
+++ b/content/other/other.tex
@@ -67,9 +67,7 @@
\paragraph{Quadrangle inequality} Die Bedingung $\forall a\leq b\leq c\leq d:
C[a][d] + C[b][c] \geq C[a][c] + C[b][d]$ ist hinreichend für beide Optimierungen.
- \paragraph{Sum over Subsets DP} $\text{res}[\text{mask}]=\sum_{i\subseteq\text{mask}}\text{in}[i]$.
- Für Summe über Supersets \code{res} einmal vorher und einmal nachher reversen.
- \sourcecode{other/sos.cpp}
+ \paragraph{Sum over Subsets DP} Siehe \emph{or} Transform, Seite \pageref{fft}.
\end{algorithm}
\begin{algorithm}{Fast Subset Sum}
@@ -82,6 +80,7 @@
\sourcecode{other/pbs.cpp}
\end{algorithm}
+\columnbreak
\begin{algorithm}{Josephus-Problem}
$n$ Personen im Kreis, jeder $k$-te wird erschossen.
\begin{description}
diff --git a/content/other/sos.cpp b/content/other/sos.cpp
deleted file mode 100644
index 892a47c..0000000
--- a/content/other/sos.cpp
+++ /dev/null
@@ -1,6 +0,0 @@
-vector<ll> res(in);
-for (int i = 1; i < ssize(res); i *= 2) {
- for (int mask = 0; mask < ssize(res); mask++){
- if (mask & i) {
- res[mask] += res[mask ^ i];
-}}}
diff --git a/test/other/sos.cpp b/test/other/sos.cpp
deleted file mode 100644
index 3ab34ea..0000000
--- a/test/other/sos.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-#include "../util.h"
-
-vector<ll> sos(const vector<ll>& in) {
- #include <other/sos.cpp>
- return res;
-}
-
-vector<ll> naive(const vector<ll>& in) {
- vector<ll> res(ssize(in));
- for (ll i = 0; i < ssize(in); i++) {
- for (ll j = 0; j <= i; j++) {
- if ((i | j) == i) {
- res[i] += in[j];
- }
- }
- }
- return res;
-}
-
-void stress_test() {
- ll tests = 0;
- for (ll i = 0; i < 1000; i++) {
- int n = Random::integer<int>(1, 100);
- auto in = Random::integers<ll>(n, -1000, 1000);
- auto got = sos(in);
- auto expected = naive(in);
- if (got != expected) cerr << "error: " << i << FAIL;
- tests += n;
- }
- cerr << "tested random queries: " << tests << endl;
-}
-
-constexpr int N = 10'000'000;
-void performance_test() {
- timer t;
- auto in = Random::integers<ll>(N, -1000, 1000);
- t.start();
- auto res = sos(in);
- t.stop();
- hash_t hash = 0;
- for (ll x : res) hash += x;
- if (t.time > 500) cerr << "too slow: " << t.time << FAIL;
- cerr << "tested performance: " << t.time << "ms (hash: " << hash << ")" << endl;
-}
-
-int main() {
- stress_test();
- performance_test();
-}
-