teamnote history merge
This commit is contained in:
BIN
2025spring/main.pdf
Normal file
BIN
2025spring/main.pdf
Normal file
Binary file not shown.
939
2025spring/main.tex
Normal file
939
2025spring/main.tex
Normal file
@@ -0,0 +1,939 @@
|
||||
\documentclass[landscape, 8pt, a4paper, oneside]{extarticle}
|
||||
%\documentclass[portrait, 8pt, a4paper, oneside, twocolumn]{extarticle}
|
||||
\usepackage{teamnote}
|
||||
|
||||
\usepackage[hangul]{kotex}
|
||||
|
||||
\usepackage[most]{tcolorbox}
|
||||
|
||||
\usepackage{multirow}
|
||||
\usepackage{adjustbox}
|
||||
\usepackage{subfiles}
|
||||
\usepackage{amsmath}
|
||||
|
||||
\usepackage{etoolbox}
|
||||
\AtBeginEnvironment{align*}{%
|
||||
|
||||
\setlength{\abovedisplayskip}{0pt}
|
||||
\setlength{\belowdisplayskip}{0pt}
|
||||
\setlength{\abovedisplayshortskip}{0pt}
|
||||
\setlength{\belowdisplayshortskip}{0pt}
|
||||
|
||||
}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\usepackage{enumitem}
|
||||
|
||||
\setlistdepth{9}
|
||||
\newlist{IdeaNote}{enumerate}{6}
|
||||
\setlist[IdeaNote]{topsep=0pt,itemsep=-1ex,partopsep=1ex,parsep=1ex}
|
||||
\setlist[IdeaNote, 1]{label= \Roman*. }
|
||||
\setlist[IdeaNote, 2]{label= \Alph*. }
|
||||
\setlist[IdeaNote, 3]{label= \arabic*. }
|
||||
\setlist[IdeaNote, 4]{label= \roman*) }
|
||||
\setlist[IdeaNote, 5]{label= \alph*) }
|
||||
\setlist[IdeaNote, 6]{label= \arabic*) }
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\usepackage{multicol}
|
||||
\setlength\columnseprule{0.5pt}
|
||||
|
||||
\teamnote{POSTECH}{ConForza}{}
|
||||
|
||||
\ShowUsage
|
||||
\ShowComplexity
|
||||
\HideAuthor
|
||||
|
||||
\begin{document}
|
||||
|
||||
\begin{multicols}{3}
|
||||
|
||||
\maketitlepage
|
||||
|
||||
\par\noindent\rule{\columnwidth}{0.4pt}
|
||||
|
||||
\section{Have you...}
|
||||
|
||||
\subsection{tried...}
|
||||
|
||||
\begin{itemize}
|
||||
\item \textcolor{red}{\textbf{Reading the problem once more?}}
|
||||
\item doubting ``obvious" things?
|
||||
\item writing obivous things?
|
||||
\item radical greedy approach?
|
||||
\item thinking in reverse direction?
|
||||
\item a greedy algorithm?
|
||||
\item network flow when your greedy algorithms stuck?
|
||||
\item a dynamic programming?
|
||||
\item checking the range of answer?
|
||||
\item random algorithm?
|
||||
\item graph modeling using states?
|
||||
\item inverting state only on odd indexes?
|
||||
\item calculating error bound on a real number usage?
|
||||
\end{itemize}
|
||||
|
||||
\subsection{checked...}
|
||||
|
||||
\begin{itemize}
|
||||
\item \textcolor{red}{\textbf{you have read the statement correctly?}}
|
||||
\item typo copying the team note?
|
||||
\item initialization on multiple test case problem?
|
||||
\item additional information from the problem?
|
||||
\item undefined behavior?
|
||||
\item overflow?
|
||||
\item function without return value?
|
||||
\item real number error?
|
||||
\item implicit conversion?
|
||||
\item comparison between signed and unsigned integer?
|
||||
\end{itemize}
|
||||
|
||||
% \pagebreak
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\section{Algorithmic Idea Note}
|
||||
|
||||
\begin{tcolorbox}[breakable, enhanced, sharp corners, colback=white, colframe=black, boxrule=1pt, left=0pt]
|
||||
|
||||
\begin{IdeaNote}
|
||||
\item Complete Search: Backtracking \& Pruning
|
||||
|
||||
\item Math
|
||||
\begin{IdeaNote}
|
||||
\item Number Theory
|
||||
\begin{IdeaNote}
|
||||
\item Prime Number
|
||||
\begin{IdeaNote}
|
||||
\item Sieve of Eratosthenes, Prime Factorization
|
||||
\item Fast Prime Verdict; Millar-Rabin
|
||||
\item Fast Prime Factorization; Pollad Rho
|
||||
\item Primitive Root
|
||||
\end{IdeaNote}
|
||||
\item Extended Euclidean Algorithm; Diophantos Equation
|
||||
\item Chinese Remainder Theorem
|
||||
\item Harmonic Lemma
|
||||
\item Floor Sum (Sum of Rational Arithmetic Sequence)
|
||||
\item Several Sieves
|
||||
\end{IdeaNote}
|
||||
\item Linear Programming
|
||||
\begin{IdeaNote}
|
||||
\item Solve (some) LP with Shortest Path
|
||||
\end{IdeaNote}
|
||||
\item FFT \& Polynomials
|
||||
\begin{IdeaNote}
|
||||
\item FFT : Convolution
|
||||
\begin{IdeaNote}
|
||||
\item High precision FFT with modulo 1e9+7
|
||||
\end{IdeaNote}
|
||||
\item NTT : Number Theoretic Tranform
|
||||
\item Quotient Ring (Formal Power Series)
|
||||
\begin{IdeaNote}
|
||||
\item Multiplication
|
||||
\item FPS : Inverse / Division
|
||||
\item Integration / Differentiation
|
||||
\item FPS : Logarithm / Exponentiation
|
||||
\item FPS : Power of Polynomial
|
||||
\item Division - Quotient \& Remainder
|
||||
\item Polynomial Taylor Shift
|
||||
\item Multipoint Evaluation
|
||||
\end{IdeaNote}
|
||||
\end{IdeaNote}
|
||||
\item Combinatorics
|
||||
\begin{IdeaNote}
|
||||
\item Labeled Combinatorial Target
|
||||
\item The Twelvefold Way (12정도)
|
||||
\item Generating Function
|
||||
\begin{IdeaNote}
|
||||
\item OGF(Ordinary Generating Function)
|
||||
\item EGF(Exponentional Generating Function)
|
||||
\item DGF?(Dirichlet Genetration Function) : Number Theory
|
||||
\end{IdeaNote}
|
||||
\item Umbral Calculus
|
||||
\end{IdeaNote}
|
||||
\end{IdeaNote}
|
||||
|
||||
\item Linear Algebra
|
||||
|
||||
\item Geometry
|
||||
\begin{IdeaNote}
|
||||
\item Basic Tools
|
||||
\begin{IdeaNote}
|
||||
\item Outer Product (CCW)
|
||||
\item Sorting by Polar
|
||||
\item Segment Intersection
|
||||
\item Closest Point
|
||||
\item Furthest Point
|
||||
\end{IdeaNote}
|
||||
\item Convex Polygon (Convex Hull)
|
||||
\begin{IdeaNote}
|
||||
\item Convex Hull Construction
|
||||
\item Convex Layer
|
||||
\item Rotating Calipers
|
||||
\item Point Containment
|
||||
\item Tangent to convex polygon
|
||||
\item Inner and Outer Tangent of two Convex's
|
||||
\end{IdeaNote}
|
||||
\item General Polygon
|
||||
\item Half Plane Intersection
|
||||
\item Delaunay Triangulation : Voronoi diagram
|
||||
\end{IdeaNote}
|
||||
|
||||
|
||||
\item Greedy
|
||||
\begin{IdeaNote}
|
||||
\item Rearrangement Inequality
|
||||
\end{IdeaNote}
|
||||
|
||||
\item DP
|
||||
\begin{IdeaNote}
|
||||
\item DP Optimization
|
||||
\begin{IdeaNote}
|
||||
\item Convex Hull Trick
|
||||
\item Alien's Trick (Lagrangian Relaxation)
|
||||
\item Slope Trick
|
||||
\end{IdeaNote}
|
||||
\end{IdeaNote}
|
||||
|
||||
\item String
|
||||
\begin{IdeaNote}
|
||||
\item KMP(Knuth-Morris-Pratt), Z, Manacher Algorithm
|
||||
\item Trie
|
||||
\item Aho-Corasick
|
||||
\item Suffix Array \& LCP Array
|
||||
\item Eertree
|
||||
\item Wavelet Tree
|
||||
\end{IdeaNote}
|
||||
|
||||
\item Graph
|
||||
\begin{IdeaNote}
|
||||
\item Searching : DFS/BFS
|
||||
\item DAG(Directed Acyclic Graph) : Topological Sorting
|
||||
\item MST(Minimum Spanning Tree)
|
||||
\begin{IdeaNote}
|
||||
\item Kruskal Algorithm
|
||||
\item Prim Algorithm
|
||||
\item Euclidian MST
|
||||
\end{IdeaNote}
|
||||
\item Shortest Path
|
||||
\begin{IdeaNote}
|
||||
\item Dijkstra Algorithm
|
||||
\item Bellman-Ford Algorithm
|
||||
\item Floyd-Warshall Algorithm
|
||||
\item Shortest Path DAG
|
||||
\end{IdeaNote}
|
||||
\item Connectivity
|
||||
\begin{IdeaNote}
|
||||
\item Offline Dynamic Connectivity (Odc)
|
||||
\item Online Dynamic Connectivity
|
||||
\begin{IdeaNote}
|
||||
\item Euler Tour Tree
|
||||
\item Top Tree
|
||||
\end{IdeaNote}
|
||||
\end{IdeaNote}
|
||||
\item DFS tree
|
||||
\begin{IdeaNote}
|
||||
\item SCC(Strongly Connected Component)
|
||||
\begin{IdeaNote}
|
||||
\item Graph Compression
|
||||
\item 2-SAT Problem
|
||||
\item Offline Incremental SCC
|
||||
\end{IdeaNote}
|
||||
\item BCC (BiConnected Component)
|
||||
\begin{IdeaNote}
|
||||
\item Blcok Cut Tree
|
||||
\item Cactus Graph
|
||||
\end{IdeaNote}
|
||||
\item Articulation Points and Bridges
|
||||
\end{IdeaNote}
|
||||
\item Network Flow
|
||||
\begin{IdeaNote}
|
||||
\item Ford-Fulkerson/Edmonds-Karp Algorithm
|
||||
\item Dinic's Algorithm
|
||||
\item Push-Relabel Algorithm
|
||||
\item MCMF(Minimum Cost Maximum Flow)
|
||||
\item Minimum s-t Cut = Maximum Flow
|
||||
\item Bipartite Matching
|
||||
\begin{IdeaNote}
|
||||
\item Minimum Vertex Cover on Bipartite
|
||||
\item Maximum Independent Set on Bipartite
|
||||
\item Minimum Path Cover on DAG
|
||||
\item Maximum Antichain on DAG
|
||||
\end{IdeaNote}
|
||||
\item Circulation
|
||||
\item General Matching
|
||||
\end{IdeaNote}
|
||||
\item Treewidth
|
||||
\end{IdeaNote}
|
||||
|
||||
\item Tree
|
||||
\begin{IdeaNote}
|
||||
\item LCA(Lowest Common Ancestor)
|
||||
\item Heavy-Light Decomposition
|
||||
\item Centroid Decomposition
|
||||
\item Link-Cut Tree
|
||||
\end{IdeaNote}
|
||||
|
||||
\item Data Structure
|
||||
\begin{IdeaNote}
|
||||
\item C++ Standard Library
|
||||
\begin{IdeaNote}
|
||||
\item Stack, Queue, List, Vector, Deque
|
||||
\item Priority Queue; Heap
|
||||
\item Set, Map : Binary Search Tree
|
||||
\item Unordered Set, Unordered Map : Hashing
|
||||
\item PBDS(Policy-Based Data Structure)
|
||||
\item Rope (Cord)
|
||||
\end{IdeaNote}
|
||||
\item Disjoint Set (Unoin-Find structure)
|
||||
\begin{IdeaNote}
|
||||
\item Union by Rank / Path Compression
|
||||
\item UF with LCA (Making Root)
|
||||
\item UF with Edge Weight
|
||||
\item UF with Unjoining
|
||||
\begin{IdeaNote}
|
||||
\item Unjoin from latest (Stack undoing)
|
||||
\item Unjoin from earliest (Queue undoing)
|
||||
\item Unjoin by Priority (Priority undoing)
|
||||
\end{IdeaNote}
|
||||
\end{IdeaNote}
|
||||
\item Sparse Table
|
||||
\item Range Query Structure
|
||||
\begin{IdeaNote}
|
||||
\item Square Root Decomposition
|
||||
\item Fenwick Tree
|
||||
\item Segment Tree
|
||||
\begin{IdeaNote}
|
||||
\item Lazy Propagation \& Generalization
|
||||
\item 금광 ST (Maximum Adjacent Sum of Given Range)
|
||||
\item PST (Persistent Segment Tree)
|
||||
\item MST (Merge Sort Tree)
|
||||
\item Segment Tree on Tree (HLD)
|
||||
\item Li-Chao Tree (Segment Add Get Min)
|
||||
\item ST Beats
|
||||
\item Kinetic ST
|
||||
\end{IdeaNote}
|
||||
\item Splay Tree
|
||||
\begin{IdeaNote}
|
||||
\item Range Reverse / Range Shift
|
||||
\end{IdeaNote}
|
||||
\end{IdeaNote}
|
||||
\end{IdeaNote}
|
||||
|
||||
\item Sorting \& Searching
|
||||
\begin{IdeaNote}
|
||||
\item Sorting
|
||||
\item Searching
|
||||
\begin{IdeaNote}
|
||||
\item Binary Search : Monotone Sequence / function
|
||||
\begin{IdeaNote}
|
||||
\item Lower bount / Upper bound
|
||||
\item LIS (Longest Increasing Subsequence)
|
||||
\item PBS (Parallel Binary Search)
|
||||
\end{IdeaNote}
|
||||
\item Ternary Search : Unimodal Sequence / function
|
||||
\begin{IdeaNote}
|
||||
\item Fibonacci Search (Golden Ratio Search)
|
||||
\end{IdeaNote}
|
||||
\end{IdeaNote}
|
||||
\end{IdeaNote}
|
||||
|
||||
\item Numerical Analysis
|
||||
\begin{IdeaNote}
|
||||
\item Numerical Differentiation
|
||||
\item Gradient Descent
|
||||
\end{IdeaNote}
|
||||
|
||||
\item Technic
|
||||
\begin{IdeaNote}
|
||||
\item Coordinate Compression
|
||||
\item Two Pointer/Sliding Window
|
||||
\item Sweeping
|
||||
\item Meet in the Middle
|
||||
\item Bitmasking
|
||||
\item Small to Large
|
||||
\item Randomization
|
||||
\begin{IdeaNote}
|
||||
\item Verifying Matrix Multiplication
|
||||
\end{IdeaNote}
|
||||
\item Query Technic
|
||||
\begin{IdeaNote}
|
||||
\item Offline Query
|
||||
\begin{IdeaNote}
|
||||
\item Mo's Algorithm
|
||||
\end{IdeaNote}
|
||||
\end{IdeaNote}
|
||||
\end{IdeaNote}
|
||||
|
||||
\end{IdeaNote}
|
||||
|
||||
\end{tcolorbox}
|
||||
|
||||
\Algorithm{astilate}
|
||||
{}{}{cpp}{source/Fundemental.cpp}
|
||||
|
||||
\Algorithm{qwerty}
|
||||
{}{}{cpp}{source/qwerty.cpp}
|
||||
|
||||
\subsection{Tips for Inequality with Rational Number}
|
||||
Let $A$, $B$, $x$, $n$ be integer, and operator `/' means floor division(quotient).
|
||||
\begin{align*}
|
||||
Ax \leqslant B & \Leftrightarrow x \leqslant B/A \\
|
||||
Ax < B & \Leftrightarrow x \leqslant (B-1)/A \\
|
||||
Ax \geqslant B & \Leftrightarrow x \geqslant (B+A-1)/A \\
|
||||
Ax > B & \Leftrightarrow x \geqslant B/A+1 \\ \\
|
||||
x < n & \Leftrightarrow x+1\leqslant n
|
||||
\end{align*}
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\section{Math}
|
||||
\subfile{source/Math/math}
|
||||
\subsection{Prime Number}
|
||||
|
||||
\subsubsection{Distribution of Prime Number}
|
||||
|
||||
\begin{center}
|
||||
\begin{tabular}{|
|
||||
>{\columncolor[HTML]{BFBFBF}}c |c|
|
||||
>{\columncolor[HTML]{BFBFBF}}c |c|
|
||||
>{\columncolor[HTML]{BFBFBF}}c |c|}
|
||||
\hline
|
||||
1e2 & 25 & 1e6 & 78,498 & 1e10 & \textless 5e8 \\ \hline
|
||||
1e3 & 168 & 1e7 & 664,579 & 1e11 & \textless 5e9 \\ \hline
|
||||
1e4 & 1,229 & 1e8 & \textless 6e6 & 1e12 & \textless 4e10 \\ \hline
|
||||
1e5 & 9,592 & 1e9 & \textless 6e7 & 1e13 & \textless 4e11 \\ \hline
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
\subsubsection{Prime Gap}
|
||||
\begin{align*}
|
||||
2 \cdot 10^{5} \text{ 이하의 소수 간극 } &\le 100\\
|
||||
2^{32} \text{ 이하의 소수 간극 } &\le 464 \\
|
||||
2^{64} \text{ 이하의 소수 간극 } &\le 1550
|
||||
\end{align*}
|
||||
|
||||
\Algorithm{Miller-Rabin Algorithm}
|
||||
{\texttt{is\_p(X)} : returns true if $X$ is prime, otherwise false.
|
||||
\begin{align*}
|
||||
\text{ When } X \le 2^{32}, D &= \{2, 7, 61\} \text{ is sufficient; } \\
|
||||
X \le 2^{64}, D &= \{p | p \text{ is prime}, p \le 37 \} \text{ is sufficient.}
|
||||
\end{align*}}
|
||||
{$\mathcal O (\log^3 X)$}
|
||||
{cpp}
|
||||
{source/Math/MillerRabin.cpp}
|
||||
|
||||
\Algorithm{Pollad Rho Algorithm}
|
||||
{ \texttt{po\_rho(N)} : returns array of prime factors of X.}
|
||||
{$\mathcal O (N^{1/4})$}
|
||||
{cpp}
|
||||
{source/Math/PolladRho.cpp}
|
||||
|
||||
\Algorithm{Primitive Root}
|
||||
{Calculate one of the primitive roots of given prime.}
|
||||
{}{cpp}
|
||||
{source/Math/PrimitiveRoot.cpp}
|
||||
|
||||
\Algorithm{Diopantos Equation(Extended Euclidian Algorithm)}
|
||||
{\texttt{diophantos(a, b)} : return one integer solution of $ax+by=1$, satisfying $0 \le x < b$. }
|
||||
{$\mathcal O \left(\log \left( \max(a, b) \right) \right)$}
|
||||
{cpp}
|
||||
{source/Math/Diophantos.cpp}
|
||||
|
||||
\Algorithm{Chinese Remainder Theorem}
|
||||
{\texttt{crt(pll p, pll q)} : return \texttt{pll r}, satisfying follows:
|
||||
\begin{align*}
|
||||
x &\equiv \texttt{p.fi} \mod \texttt{p.se} \\
|
||||
\text{and } x &\equiv \texttt{q.fi} \mod \texttt{q.se} \\
|
||||
\leftrightarrow x &\equiv \texttt{r.fi} \mod \texttt{r.se}
|
||||
\end{align*}
|
||||
If there's no such \texttt{r}, return $\{-1, -1\}$.
|
||||
}
|
||||
{$\mathcal O(\log A)$}
|
||||
{cpp}
|
||||
{source/Math/CRT.cpp}
|
||||
|
||||
\Algorithm{Harmonic Lemma}
|
||||
{\texttt{f(N)} : return the value
|
||||
$$\sum_{i=1}^{N} \left\lfloor \frac{N}{i} \right\rfloor = \left\lfloor \frac{N}{1}\right\rfloor + \left\lfloor \frac{N}{2} \right\rfloor + \cdots + \left\lfloor \frac{N}{N}\right\rfloor $$
|
||||
Using the fact that $\left\lfloor \frac{N}{x} \right\rfloor$ has $\mathcal O(\sqrt N)$ different values.}
|
||||
{$\mathcal O(\sqrt N )$}
|
||||
{cpp}
|
||||
{source/Math/Harmonic.cpp}
|
||||
|
||||
\Algorithm{Floor Sum (Sum of Floor of Rational Arithmetic Sequence)}
|
||||
{\texttt{floor\_sum(A, B, C, N)} : return the value
|
||||
$$\sum_{x=0}^{N-1} \left\lfloor \frac{Ax+B}{C} \right\rfloor $$}
|
||||
{$\mathcal O(\log N)$}
|
||||
{cpp}
|
||||
{source/Math/FloorSum.cpp}
|
||||
|
||||
\Algorithm{FFT - Convolution}
|
||||
{}
|
||||
{$\mathcal O (N\log N)$}
|
||||
{cpp}
|
||||
{source/Math/FFTConv.cpp}
|
||||
|
||||
|
||||
|
||||
\Algorithm{NTT - Number Theoretic Transform}
|
||||
{helloworld}
|
||||
{}
|
||||
{cpp}
|
||||
{source/Math/NTT.cpp}
|
||||
|
||||
\subsubsection{Good prime numbers to run NTT}
|
||||
\begin{center}
|
||||
\begin{adjustbox}{width=0.8\columnwidth}
|
||||
\begin{tabular}{|c|c|
|
||||
>{\columncolor[HTML]{C0C0C0}}l |}
|
||||
\hline
|
||||
595 591 169 & 71\textless{}\textless{}23|1 & \cellcolor[HTML]{C0C0C0} \\ \cline{1-2}
|
||||
645 922 817 & 77\textless{}\textless{}23|1 & \cellcolor[HTML]{C0C0C0} \\ \cline{1-2}
|
||||
897 581 057 & 107\textless{}\textless{}23|1 & \cellcolor[HTML]{C0C0C0} \\ \cline{1-2}
|
||||
998 244 353 & 119\textless{}\textless{}23|1 & \cellcolor[HTML]{C0C0C0} \\ \cline{1-2}
|
||||
1 300 234 241 & 155\textless{}\textless{}23|1 & \cellcolor[HTML]{C0C0C0} \\ \cline{1-2}
|
||||
1 224 736 769 & 73\textless{}\textless{}24|1 & \cellcolor[HTML]{C0C0C0} \\ \cline{1-2}
|
||||
2 130 706 433 & 127\textless{}\textless{}24|1 & \cellcolor[HTML]{C0C0C0} \\ \cline{1-2}
|
||||
167 772 161 & 5\textless{}\textless{}25|1 & \cellcolor[HTML]{C0C0C0} \\ \cline{1-2}
|
||||
469 762 049 & 7\textless{}\textless{}26|1 & \multirow{-9}{*}{\cellcolor[HTML]{C0C0C0}$\omega$ = 3} \\ \hline
|
||||
\end{tabular}
|
||||
\end{adjustbox}
|
||||
\end{center}
|
||||
|
||||
\Algorithm{Polynomial (Formal Power Series)}
|
||||
{}
|
||||
{}
|
||||
{cpp}
|
||||
{source/Math/Polynomial.cpp}
|
||||
|
||||
\subsection{Combinatorics}
|
||||
\subsubsection{Labeled Combinatorial Target}
|
||||
\begin{itemize}
|
||||
\item Permutation, Combination (with, w/o repetition)
|
||||
\begin{itemize}
|
||||
\item Permutation $_nP_r = \frac{n!}{r!(n-r)!}$
|
||||
\item Combination $_nC_r = \binom n k = \frac{n!}{r!}$
|
||||
\item Permutation with repetition $_n\Pi_r = n^r$
|
||||
\item Combination with repetition $_nH_r = _{n+r-1}C_r$
|
||||
\end{itemize}
|
||||
\item Catalan Number $C_n$ : the number of regular bracket string of length $2n$.
|
||||
\begin{itemize}
|
||||
\item $C_n = \frac{1}{n+1}\binom {2n}n$
|
||||
\item $C_n : 1, 1, 2, 5, 14, 42, 132,429,1430,\cdots$ (from index 0)
|
||||
\item OGF of $C_n$ : $c(x) = 1+xc(x)^2, c(c) = \frac{1-\sqrt{1-4x}}{2x}$
|
||||
\item Catalan's triangle $C(n, k)$ : the number of string with $n$ X's, $k$ Y's, where the number of Y's is not greater than the number of X's when written down the string.
|
||||
\begin{itemize}
|
||||
\item i.e. $C(4, 3)$ : XXXXYYY, XXYXYYX are OK, but XXYYYXX is not OK.
|
||||
\item $C(n, k) = \binom{n+k}{k} - \binom{n+k}{k-1} = \frac{n-k+1}{n+1}\binom{n+k}{k}$
|
||||
\item We can give the condition relax : $C_m(n, k)$ : the number of string with $n$ X's, $k$ Y's, where the number of Y's is not greater than (the number of X's) + $m$ when written down the string.
|
||||
\item $C_m(n, k) = \binom{n+k}{k}-\binom{n+k}{k-m}$ when $m\leqslant k \leqslant n+m-1$.
|
||||
\item $C_1(n, k) = C(n, k)$
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
\item Derangement(교란순열) $D_n$ : the number of permutation of length $n$ which $\forall i\;p_i \neq i$.
|
||||
\begin{itemize}
|
||||
\item $D_n : 1, 0, 1, 2, 9, 44, 265, 1854, 14833, 133496,1334961 \cdots$ (from index 0)
|
||||
\item EGF of $D_n$ : $D(x) = \sum_{n=0} \frac{D_n}{n!}x^n = \frac{e^{-x}}{1-x}$
|
||||
\end{itemize}
|
||||
\item Stirling Number of the 1st/2nd kind.
|
||||
\begin{itemize}
|
||||
\item Unsigned Stirling Number of the 1st kind $c(n, k) = {n \brack k}$ : the number of permutation of length n with k disjoint cycles.
|
||||
\begin{itemize}
|
||||
\item $c(n+1, k) = n \times c(n, k) + c(n, k-1)$
|
||||
\item with boundary condition $c(0, 0) = 1, c(n, 0) = c(0, k) = 0 \; \forall n, k>0$
|
||||
\item $c(n, k)$\\
|
||||
\begin{tabular}{|
|
||||
>{\columncolor[HTML]{ECECEC}}r |
|
||||
>{\columncolor[HTML]{F8F9FA}}r |r|r|r|l|l|l|}
|
||||
\hline
|
||||
\cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} \textit{n\textbackslash{}k}} & \cellcolor[HTML]{ECECEC}{\color[HTML]{202122} \textbf{0}} & \cellcolor[HTML]{ECECEC}{\color[HTML]{202122} \textbf{1}} & \cellcolor[HTML]{ECECEC}{\color[HTML]{202122} \textbf{2}} & \cellcolor[HTML]{ECECEC}{\color[HTML]{202122} \textbf{3}} & \multicolumn{1}{r|}{\cellcolor[HTML]{ECECEC}{\color[HTML]{202122} \textbf{4}}} & \multicolumn{1}{r|}{\cellcolor[HTML]{ECECEC}{\color[HTML]{202122} \textbf{5}}} & \multicolumn{1}{r|}{\cellcolor[HTML]{ECECEC}{\color[HTML]{202122} \textbf{6}}} \\ \hline
|
||||
{\color[HTML]{202122} \textbf{0}} & {\color[HTML]{202122} 1} & \multicolumn{1}{l|}{} & \multicolumn{1}{l|}{} & \multicolumn{1}{l|}{} & & & \\ \hline
|
||||
{\color[HTML]{202122} \textbf{1}} & {\color[HTML]{202122} 0} & \cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} 1} & \multicolumn{1}{l|}{} & \multicolumn{1}{l|}{} & & & \\ \hline
|
||||
{\color[HTML]{202122} \textbf{2}} & {\color[HTML]{202122} 0} & \cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} 1} & \cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} 1} & \multicolumn{1}{l|}{} & & & \\ \hline
|
||||
{\color[HTML]{202122} \textbf{3}} & {\color[HTML]{202122} 0} & \cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} 2} & \cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} 3} & \cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} 1} & & & \\ \hline
|
||||
{\color[HTML]{202122} \textbf{4}} & {\color[HTML]{202122} 0} & \cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} 6} & \cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} 11} & \cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} 6} & \multicolumn{1}{r|}{\cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} 1}} & & \\ \hline
|
||||
{\color[HTML]{202122} \textbf{5}} & {\color[HTML]{202122} 0} & \cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} 24} & \cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} 50} & \cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} 35} & \multicolumn{1}{r|}{\cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} 10}} & \multicolumn{1}{r|}{\cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} 1}} & \\ \hline
|
||||
{\color[HTML]{202122} \textbf{6}} & {\color[HTML]{202122} 0} & \cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} 120} & \cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} 274} & \cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} 225} & \multicolumn{1}{r|}{\cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} 85}} & \multicolumn{1}{r|}{\cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} 15}} & \multicolumn{1}{r|}{\cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} 1}} \\ \hline
|
||||
\end{tabular}
|
||||
\item OGF of ${n \brack k}$ : for fixed $n$, $\sum_{k=0}^n {n \brack k} x^k = x(x+1)(x+2)\cdots(x+n-1)$ : we can calculate it by polynomial shift \& divide and conquer
|
||||
\item EGF of ${n \brack k}$ : for fixed $k$, $\sum_{n=k}^\infty {n \brack k} \frac{x^n}{n!} = \frac{(-\log(1-z))^k}{k!} $
|
||||
\item Signed Stirling Number of the 1st kind $s(n, k) = (-1)^{n-k}c(n, k)$
|
||||
\item EGF of $s(n, k)$ : for fixed $k$, $\sum_{n=k}^\infty s(n, k) \frac{x^n}{n!} = \frac{(\log(1+z))^k}{k!} $
|
||||
\end{itemize}
|
||||
\item Stirling Number of the 2nd kind $S(n, k) = {n \brace k}$ : the number of partition of $n$ labeled objects into $k$ nonempty unlabelled subsets.
|
||||
\begin{itemize}
|
||||
\item $S(n, k) = \frac{1}{k!}\sum_{i=0}^k(-1)^{k-i}\binom{k}{i}i^n$
|
||||
\item $S(n, k)$\\
|
||||
\begin{tabular}{|
|
||||
>{\columncolor[HTML]{ECECEC}}r |
|
||||
>{\columncolor[HTML]{F8F9FA}}r |r|r|r|l|l|l|}
|
||||
\hline
|
||||
\cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} \textit{\textbf{n\textbackslash{}k}}} & \cellcolor[HTML]{ECECEC}{\color[HTML]{202122} \textbf{0}} & \cellcolor[HTML]{ECECEC}{\color[HTML]{202122} \textbf{1}} & \cellcolor[HTML]{ECECEC}{\color[HTML]{202122} \textbf{2}} & \cellcolor[HTML]{ECECEC}{\color[HTML]{202122} \textbf{3}} & \multicolumn{1}{r|}{\cellcolor[HTML]{ECECEC}{\color[HTML]{202122} \textbf{4}}} & \multicolumn{1}{r|}{\cellcolor[HTML]{ECECEC}{\color[HTML]{202122} \textbf{5}}} & \multicolumn{1}{r|}{\cellcolor[HTML]{ECECEC}{\color[HTML]{202122} \textbf{6}}} \\ \hline
|
||||
{\color[HTML]{202122} \textbf{0}} & {\color[HTML]{202122} 1} & \multicolumn{1}{l|}{} & \multicolumn{1}{l|}{} & \multicolumn{1}{l|}{} & & & \\ \hline
|
||||
{\color[HTML]{202122} \textbf{1}} & {\color[HTML]{202122} 0} & \cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} 1} & \multicolumn{1}{l|}{} & \multicolumn{1}{l|}{} & & & \\ \hline
|
||||
{\color[HTML]{202122} \textbf{2}} & {\color[HTML]{202122} 0} & \cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} 1} & \cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} 1} & \multicolumn{1}{l|}{} & & & \\ \hline
|
||||
{\color[HTML]{202122} \textbf{3}} & {\color[HTML]{202122} 0} & \cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} 1} & \cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} 3} & \cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} 1} & & & \\ \hline
|
||||
{\color[HTML]{202122} \textbf{4}} & {\color[HTML]{202122} 0} & \cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} 1} & \cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} 7} & \cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} 6} & \multicolumn{1}{r|}{\cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} 1}} & & \\ \hline
|
||||
{\color[HTML]{202122} \textbf{5}} & {\color[HTML]{202122} 0} & \cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} 1} & \cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} 15} & \cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} 25} & \multicolumn{1}{r|}{\cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} 10}} & \multicolumn{1}{r|}{\cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} 1}} & \\ \hline
|
||||
{\color[HTML]{202122} \textbf{6}} & {\color[HTML]{202122} 0} & \cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} 1} & \cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} 31} & \cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} 90} & \multicolumn{1}{r|}{\cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} 65}} & \multicolumn{1}{r|}{\cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} 15}} & \multicolumn{1}{r|}{\cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} 1}} \\ \hline
|
||||
\end{tabular}
|
||||
\item OGF of ${n \brace k}$ : for fixed $n$, $\sum_{k=0}^n{n\brace k}x^k=T_n(x)$, where $T_n(x) = e^{-x}\sum_{k=0}^{\infty}\frac{k^n}{k!}x^k$ is Touchard Polynomials.
|
||||
\item EGF of ${n \brace k}$ : for fixed $k$, $\sum_{n=k}^\infty{n\brace k}x^n=\frac{(e^x-1)^k}{k!}$
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
\item
|
||||
\item Bell Number $B_n$ : the number of partition of set with size $n$.
|
||||
\begin{itemize}
|
||||
\item i.e. partitionize $\{a, b, c\}$ is $\{\{a\}, \{b\}, \{c\}\}, \{\{a , b\}, \{c\}\}$, $\{\{b, c\}, \{a\}\}, \{\{c, a\}, \{b\}\}, \{\{a, b, c\}\}$. Therefore, $B_3 = 5$.
|
||||
\item $B_n : 1,1,2,5,15,52,203,877,4140,\cdots$ (from index 0)
|
||||
\item $B_n = \sum_{k=0}^n{n \brace k}$ (2nd kind of stirling number)
|
||||
\item EGF of $B_n$ : $B(x) = \sum_{n=0}\frac{B_n}{n!}x^n=e^{e^x-1}$
|
||||
\item Ordered Bell Number(Fubini Number) $a_n$ : the number of distinct weak ordering on a set of n elements.
|
||||
\begin{itemize}
|
||||
\item $a_n : 1, 1, 3, 13, 75, 541, 4683, 47293, 545835, 7087261, \cdots$
|
||||
\item $a_n = \sum_{k=0}^nk!{n \brace k}$ (stirling number of the 2nd kind)
|
||||
\item EGF of $a_n$ : $a(x) = \sum_{n=0}^\infty \frac{a_n}{n!}x^n = \frac{1}{2-e^x}$
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
\item Integer Partition $P(n, k)$ : the number of partitions of $n$ into exactly $k$ parts.
|
||||
\begin{itemize}
|
||||
\item i.e. $P(4, 2) = 2$ since $4 = 1+3 = 2+2$
|
||||
\item we also say $P(n) = \sum_{k=1}^{n}P(n, k)$
|
||||
\item $P(n, k)$\\
|
||||
\begin{tabular}{|
|
||||
>{\columncolor[HTML]{EAECF0}}c |
|
||||
>{\columncolor[HTML]{F8F9FA}}l |
|
||||
>{\columncolor[HTML]{F8F9FA}}l |
|
||||
>{\columncolor[HTML]{F8F9FA}}l |
|
||||
>{\columncolor[HTML]{F8F9FA}}l |
|
||||
>{\columncolor[HTML]{F8F9FA}}l |
|
||||
>{\columncolor[HTML]{F8F9FA}}l |
|
||||
>{\columncolor[HTML]{F8F9FA}}l |
|
||||
>{\columncolor[HTML]{F8F9FA}}l |
|
||||
>{\columncolor[HTML]{F8F9FA}}l |}
|
||||
\hline
|
||||
\multicolumn{1}{|r|}{\cellcolor[HTML]{F8F9FA}{\color[HTML]{202122} \textit{\textbf{n\textbackslash{}k}}}} & \multicolumn{1}{c|}{\cellcolor[HTML]{EAECF0}{\color[HTML]{202122} \textbf{1}}} & \multicolumn{1}{c|}{\cellcolor[HTML]{EAECF0}{\color[HTML]{202122} \textbf{2}}} & \multicolumn{1}{c|}{\cellcolor[HTML]{EAECF0}{\color[HTML]{202122} \textbf{3}}} & \multicolumn{1}{c|}{\cellcolor[HTML]{EAECF0}{\color[HTML]{202122} \textbf{4}}} & \multicolumn{1}{c|}{\cellcolor[HTML]{EAECF0}{\color[HTML]{202122} \textbf{5}}} & \multicolumn{1}{c|}{\cellcolor[HTML]{EAECF0}{\color[HTML]{202122} \textbf{6}}} & \multicolumn{1}{c|}{\cellcolor[HTML]{EAECF0}{\color[HTML]{202122} \textbf{7}}} & \multicolumn{1}{c|}{\cellcolor[HTML]{EAECF0}{\color[HTML]{202122} \textbf{8}}} & \multicolumn{1}{c|}{\cellcolor[HTML]{EAECF0}{\color[HTML]{202122} \textbf{9}}} \\ \hline
|
||||
{\color[HTML]{202122} \textbf{1}} & {\color[HTML]{202122} 1} & {\color[HTML]{202122} } & {\color[HTML]{202122} } & {\color[HTML]{202122} } & {\color[HTML]{202122} } & {\color[HTML]{202122} } & {\color[HTML]{202122} } & {\color[HTML]{202122} } & {\color[HTML]{202122} } \\ \hline
|
||||
{\color[HTML]{202122} \textbf{2}} & {\color[HTML]{202122} 1} & {\color[HTML]{202122} 1} & {\color[HTML]{202122} } & {\color[HTML]{202122} } & {\color[HTML]{202122} } & {\color[HTML]{202122} } & {\color[HTML]{202122} } & {\color[HTML]{202122} } & {\color[HTML]{202122} } \\ \hline
|
||||
{\color[HTML]{202122} \textbf{3}} & {\color[HTML]{202122} 1} & {\color[HTML]{202122} 1} & {\color[HTML]{202122} 1} & {\color[HTML]{202122} } & {\color[HTML]{202122} } & {\color[HTML]{202122} } & {\color[HTML]{202122} } & {\color[HTML]{202122} } & {\color[HTML]{202122} } \\ \hline
|
||||
{\color[HTML]{202122} \textbf{4}} & {\color[HTML]{202122} 1} & {\color[HTML]{202122} 2} & {\color[HTML]{202122} 1} & {\color[HTML]{202122} 1} & {\color[HTML]{202122} } & {\color[HTML]{202122} } & {\color[HTML]{202122} } & {\color[HTML]{202122} } & {\color[HTML]{202122} } \\ \hline
|
||||
{\color[HTML]{202122} \textbf{5}} & {\color[HTML]{202122} 1} & {\color[HTML]{202122} 2} & {\color[HTML]{202122} 2} & {\color[HTML]{202122} 1} & {\color[HTML]{202122} 1} & {\color[HTML]{202122} } & {\color[HTML]{202122} } & {\color[HTML]{202122} } & {\color[HTML]{202122} } \\ \hline
|
||||
{\color[HTML]{202122} \textbf{6}} & {\color[HTML]{202122} 1} & {\color[HTML]{202122} 3} & {\color[HTML]{202122} 3} & {\color[HTML]{202122} 2} & {\color[HTML]{202122} 1} & {\color[HTML]{202122} 1} & {\color[HTML]{202122} } & {\color[HTML]{202122} } & {\color[HTML]{202122} } \\ \hline
|
||||
{\color[HTML]{202122} \textbf{7}} & {\color[HTML]{202122} 1} & {\color[HTML]{202122} 3} & {\color[HTML]{202122} 4} & {\color[HTML]{202122} 3} & {\color[HTML]{202122} 2} & {\color[HTML]{202122} 1} & {\color[HTML]{202122} 1} & {\color[HTML]{202122} } & {\color[HTML]{202122} } \\ \hline
|
||||
{\color[HTML]{202122} \textbf{8}} & {\color[HTML]{202122} 1} & {\color[HTML]{202122} 4} & {\color[HTML]{202122} 5} & {\color[HTML]{202122} 5} & {\color[HTML]{202122} 3} & {\color[HTML]{202122} 2} & {\color[HTML]{202122} 1} & {\color[HTML]{202122} 1} & {\color[HTML]{202122} } \\ \hline
|
||||
{\color[HTML]{202122} \textbf{9}} & {\color[HTML]{202122} 1} & {\color[HTML]{202122} 4} & {\color[HTML]{202122} 7} & {\color[HTML]{202122} 6} & {\color[HTML]{202122} 5} & {\color[HTML]{202122} 3} & {\color[HTML]{202122} 2} & {\color[HTML]{202122} 1} & {\color[HTML]{202122} 1} \\ \hline
|
||||
\end{tabular}
|
||||
\end{itemize}
|
||||
\item 12정도(the Twelvefold Way) : the number of functions \\
|
||||
(Domain $|N| = n$, Codomain $|X| = x$)\\
|
||||
\begin{tabular}{|
|
||||
>{\columncolor[HTML]{F8F9FA}}c |c|c|c|}
|
||||
\hline
|
||||
\cellcolor[HTML]{EAECF0}{\color[HTML]{202122} \textit{\textbf{$f$-class}}} & \cellcolor[HTML]{EAECF0}{\color[HTML]{202122} \textbf{Any $f$}} & \cellcolor[HTML]{EAECF0}{\color[HTML]{202122} \textbf{Injective}} & \cellcolor[HTML]{EAECF0}{\color[HTML]{202122} \textbf{Surjective}} \\ \hline
|
||||
{\color[HTML]{202122} \textbf{Distinct $f$}} & \textit{$_n\Pi_x$} & \textit{$_xP_n$} & $x!{x\brace n}$ \\ \hline
|
||||
{\color[HTML]{202122} \textit{\textbf{\begin{tabular}[c]{@{}c@{}}$S_n$ orbits\\ $f \circ S_n$\end{tabular}}}} & \textit{$_xH_n$} & \textit{$_xC_n$} & $_{n-1}C_{n-x}$ \\ \hline
|
||||
{\color[HTML]{202122} \textit{\textbf{\begin{tabular}[c]{@{}c@{}}$S_x$ orbits\\ $S_x \circ f$\end{tabular}}}} & $\sum_{k=0}^x {n \brace k}$ & $[n \leqslant x]$ & ${n \brace x}$ \\ \hline
|
||||
{\color[HTML]{202122} \textit{\textbf{\begin{tabular}[c]{@{}c@{}}$S_n\times S_x$ orbits\\ $S_x \circ f \circ S_n$\end{tabular}}}} & $P(n+x, x)$ & $[n \leqslant x]$ & $P(n, x)$ \\ \hline
|
||||
\end{tabular}
|
||||
\end{itemize}
|
||||
|
||||
\Algorithm{General Lucas Comb}
|
||||
{}
|
||||
{}
|
||||
{cpp}
|
||||
{source/Math/general_lucas.cpp}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\section{Linear Algebra}
|
||||
\Algorithm{Matrix}
|
||||
{}
|
||||
{}
|
||||
{cpp}
|
||||
{"source/Linear Algebra/Matrix.cpp"}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\section{Geometry}
|
||||
\Algorithm{Mindset}
|
||||
{}
|
||||
{}
|
||||
{cpp}
|
||||
{source/Geometry/Mindset.cpp}
|
||||
|
||||
% \Algorithm{Point in Convex Polygon}
|
||||
% {\texttt{isunder(upper\_hull[], (length of upper\_hull), x)} : return true if $x$(point) is under upper\_hull, otherwise false;
|
||||
|
||||
% \texttt{isunder(lower\_hull[], (length of lower\_hull), x, true)} : return true if $x$(point) is over lower\_hull, otherwise false.
|
||||
|
||||
% Point in Polygon : isunder(upper, u, x) \&\& isupper(lower, u, x, true)}
|
||||
% {}
|
||||
% {cpp}
|
||||
% {source/Geometry/PointInConvexPolygon.cpp}
|
||||
|
||||
\Algorithm{kactl templete}
|
||||
{}
|
||||
{}
|
||||
{cpp}
|
||||
{source/Geometry/geometry_kaere.cpp}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\section{Greedy}
|
||||
\subsection{Rearrange Inequality - Extensions}
|
||||
Let $A_i, B_i$ be non-decreasing sequence of length $n$, and $p$ be some permutation, and let $inc := (1, 2, \dots, n-1, n), \;dec := (n, n-1, \dots, 2, 1)$.
|
||||
|
||||
\begin{align*}
|
||||
S(p) &= \sum_{i=1}^n A_i B_{p_i}
|
||||
&& \text{ maximize } S &&&\Rightarrow p : inc&&&&\\
|
||||
& && \text{ minimize } S &&&\Rightarrow p:dec&&&&\\
|
||||
P_{max}(p) &= \max_i(A_iB_{p_i})
|
||||
&& \text{ minimize } P_{max} &&&\Rightarrow p : dec&&&&\\
|
||||
P_{min}(p) &= \min_i(A_iB_{p_i})
|
||||
&& \text{ maximize } P_{min} &&&\Rightarrow p:dec&&&&\\
|
||||
A_{max}(p) &= \max_i(A_i+B_{p_i}) && \text
|
||||
{ minimize } A_{max} &&& \Rightarrow p:dec&&&&\\
|
||||
A_{min}(p) &= \min_i(A_i+B_{p_i}) && \text{ maximize } A_{min} &&& \Rightarrow p:dec&&&&\\
|
||||
D_{max}(p) &= \max_i|A_i-B_{p_i}| && \text{ minimize } D_{max} &&& \Rightarrow p:inc&&&&\\
|
||||
D_{min}(p) &= \min_i|A_i-B_{p_i}| && \text{ maximize } D_{min} &&& \Rightarrow p:?&&&&\\
|
||||
\end{align*}
|
||||
\begin{align*}
|
||||
\text{ Permutate } A \text{ s.t.} \text{ maximize } & \sum_{i=1}^n {A_i A_{i+1}} \;(\text{Let } A_{n+1} = A_1) \\ &\Rightarrow \text{ Pendulum Arrangement }
|
||||
\end{align*}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\section{DP}
|
||||
|
||||
\Algorithm{LIS}
|
||||
{}{}{cpp}{source/DP/LIS.cpp}
|
||||
|
||||
\subsection{DP Optimization}
|
||||
|
||||
\subsubsection{Convex Hull Optimization}
|
||||
\begin{align*}
|
||||
\text{ Recurrence : }& D[i] = \min_{j<i} { \left(B[j] \times A[i] + D[j] \right)}\\
|
||||
\text{ Complexity : }& \mathcal O(N^2) \rightarrow \mathcal O(N\log N)
|
||||
\end{align*}
|
||||
|
||||
\subsubsection{Divide and Conquer Optimization}
|
||||
\begin{align*}
|
||||
\text{ Recurrence : }& D[i][j] = \min_{k<i} { \left(D[i-1][k] + C[k][j]\right)}\\
|
||||
\text{ Condition : }& C[i][j] \text{ is Monge } \\
|
||||
(\text{ if }a \leqslant b \leqslant c \leqslant d, &\text{ then } C[a][c] + C[b][d] \leqslant C[a][d] + C[b][c] )\\
|
||||
\text{ Complexity : }& \mathcal O(KN^2) \rightarrow \mathcal O(KN\log N)
|
||||
\end{align*}
|
||||
|
||||
\inputminted[]{cpp}{source/DP/DnC.cpp}
|
||||
|
||||
\subsubsection{Monotone Queue Optimization}
|
||||
\begin{align*}
|
||||
\text{ Recurrence : }& D[i] = \min_{j<i} { \left(D[j] + C[j][i]\right)}\\
|
||||
\text{ Condition : }& C[i][j] \text{ is Monge } \\
|
||||
\text{ Complexity : }& \mathcal O(N^2) \rightarrow \mathcal O(N\log N)
|
||||
\end{align*}
|
||||
|
||||
\subsubsection{Knuth's Optimization}
|
||||
\begin{align*}
|
||||
\text{ Recurrence : }& D[i][j] = \min_{i\leqslant k < i} { \left(D[i][k] + D[k+1][j] \right) + C[i][j] } \\
|
||||
\text{ Condition : }& C[i][j] \text{ is Monge } \& \\ & C[a][d] \geqslant C[b][c] \text{ for } a \leqslant b \leqslant c \leqslant d \\
|
||||
\text{ Complexity : }& \mathcal O(N^3) \rightarrow \mathcal O(N^2)
|
||||
\end{align*}
|
||||
|
||||
구간에 대해 동적 계획법(DP)을 수행할 때, 다음과 같은 점화식이 있다고 가정합니다:
|
||||
\[ a[i][j] = \min_{i < k < j} \big( a[i][k] + a[k][j] \big) + f(i, j) \]
|
||||
여기서 (최소화된) 최적의 \( k \)가 \( i \)와 \( j \) 모두에 대해 증가한다고 하면, 구간의 길이에 따라 DP를 계산하며 \( a[i][j] \)에 대해 \( k = p[i][j] \)를 \( p[i][j-1] \)부터 \( p[i+1][j] \) 사이에서만 탐색하면 됩니다.
|
||||
|
||||
\subsubsection{Aliens Trick (Lagrangian relaxation)}
|
||||
\begin{align*}
|
||||
\text{ Recurrence : }& D[k][i] = \min_{j<i} \left( D[k-1][j] + C[j+1][i]\right)\\
|
||||
\text{ Condition : }& D[x][N] \text{ is convex } ( \text{ is implied when } C[i][j] \text{ is Monge } ) \\
|
||||
& \left( f(x+1)-f(x) \leqslant f(x+2)-f(x+1) \right)\\
|
||||
\text{ Complexity : }& \mathcal O(KN^2) \rightarrow \mathcal O(N^2 \log |W|)
|
||||
\end{align*}
|
||||
\subsubsection{Slope Trick}
|
||||
13323 BOJ 수열 1/2. 수열 A가 주어진다. 증가수열 B에 대해, $\sum_{i=1}^N |A_i - B_i|$를 최소화하고, 그 B를 찾아라.
|
||||
\inputminted[]{cpp}{source/DP/SlopeTrick.cpp}
|
||||
|
||||
\Algorithm{LineContainer}
|
||||
{}
|
||||
{$\mathcal O(\log N)$}
|
||||
{cpp}
|
||||
{source/DP/LineContainer.cpp}
|
||||
|
||||
\Algorithm{SoS}
|
||||
{}
|
||||
{$\mathcal O(N*2^N)$}
|
||||
{cpp}
|
||||
{source/DP/SoS.cpp}
|
||||
|
||||
% \Algorithm{}
|
||||
% {}
|
||||
% {$\mathcal O(N?)$}
|
||||
% {cpp}
|
||||
% {source/}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\section{String}
|
||||
|
||||
% \Algorithm{std::string}
|
||||
% {}
|
||||
% {}
|
||||
% {}
|
||||
% {source/String/std::string.cpp}
|
||||
|
||||
\Algorithm{KMP}
|
||||
{}
|
||||
{}
|
||||
{cpp}
|
||||
{source/String/KMP.cpp}
|
||||
|
||||
\Algorithm{F, Z, M, SA(Suffix Array), LCP(Longest Common Prefix)}
|
||||
{For string s(1-indexed) of length N;
|
||||
\begin{align*}
|
||||
\texttt{F[i] = }& \text{maximum } k<i && \text{ s.t. } s[1\dots k] = s[i-k+1 \dots i]\\
|
||||
\texttt{Z[i] = }& \text{maximum } k && \text{ s.t. } s[1\dots k] = s[i \dots i+k-1]\\
|
||||
\texttt{M[i] = }& \text{maximum } k && \text{ s.t. } s[i-k+1 \dots i+k-1] \text{ is palindrom.}\\
|
||||
\texttt{SA[i] = }& k && \text{ s.t. } s[k\dots N] \text{ is the } i^{th} \text{ smallest of } \\
|
||||
& && \{s[1\dots N],\; s[2\dots N],\; \cdots,\; s[N\dots N]\}\\
|
||||
\texttt{LCP[i] = }& \text{maximum } k && \text{ s.t. } s[SA[i-1]\dots SA[i-1]+k-1]\\
|
||||
& && = s[SA[i] \dots SA[i]+k-1]
|
||||
\end{align*}
|
||||
}
|
||||
{$\mathcal O(N),\mathcal O(N),\mathcal O(N),\mathcal O(N\log N),\mathcal O(N)$, respectively}
|
||||
{cpp}
|
||||
{source/String/F_Z_M_SA_LCP.cpp}
|
||||
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\section{Graph}
|
||||
|
||||
\Algorithm{SCC - Tarjan Algorithm}
|
||||
{\texttt{scn[i]} : SCC number of node $i$, \texttt{nscc} : the number of SCCs}
|
||||
{}
|
||||
{cpp}
|
||||
{source/Graph/TarjanSCC.cpp}
|
||||
|
||||
\Algorithm{Bipartite Matching - with DFS}
|
||||
{Let's say that graph is bipartite. And Let's say that one group is $A$, and the other graph is $B$. $|A|=N$, $|B|=M$. \texttt{matching(c = s)} : add one matching from $s \in A$. If successfully matched, return true; otherwise return false. \texttt{selby[i] = } store $s\in A$, s.t. $i\in B$ is matched with $s$. \\ (e.g.) \texttt{forr(i, n) ans += matching(c=i);}}
|
||||
{$\mathcal O(VE)$}
|
||||
{cpp}
|
||||
{source/Graph/BipartiteMatching.cpp}
|
||||
|
||||
\subsubsection{Minimum Vertex Cover on Bipartite Graph(Kőnig's Therorem)}
|
||||
On bipartite graph, $$|\texttt{Minimum Vertex Cover}| = |\texttt{Maximum Matching}|$$
|
||||
|
||||
To find Minimum Vertex Cover, ( \added )
|
||||
|
||||
\subsubsection{Maximum Independent Set on Bipartite Graph}
|
||||
On bipartite graph, $$|\texttt{Maximum Independent Set}|=|V|-|\texttt{Maximum Matching}|$$
|
||||
|
||||
* Note : Complement of the Vertex Cover is the Independent Set.
|
||||
|
||||
\subsubsection{Minimum Path Cover on DAG}
|
||||
Let's think about the bipartite graph, with vertex set A and B, satisfying follow property:
|
||||
|
||||
\begin{itemize}
|
||||
\item If there's edge from node $i$ to node $j$ on DAG, then there's edge connecting $i^{th}$ node of A and $j^{th}$ node of B, and vice versa.
|
||||
\end{itemize}
|
||||
|
||||
Then following holds:
|
||||
|
||||
$|\texttt{Minimum Path Cover of DAG}| = |\texttt{Maximum Matching on Bipartite Graph}|$
|
||||
|
||||
|
||||
\subsubsection{Maximum Antichain on DAG(Dilworth's Theorem)}
|
||||
On DAG, $$|\texttt{Minimum Path Cover}| = |\texttt{Maximum Antichain}|$$
|
||||
|
||||
|
||||
\Algorithm{Network Flow - Dinic}
|
||||
{Construct graph with \texttt{connect(from, to, capacity, isDirected);}. Find the flow from $S$ to $T$ with \texttt{flow(S, T);}. }
|
||||
{$\mathcal O(V^2E)$, but it works like magic.}
|
||||
{cpp}
|
||||
{source/Graph/Dinic.cpp}
|
||||
|
||||
\Algorithm{MCMF - with SPFA}
|
||||
{Construct graph with \texttt{connect(from, to, capacity, cost);}. Find the maximum flow and corresponding minimum cost from $S$ to $T$ with \texttt{flow(S, T);}.}
|
||||
{$\mathcal O(VEf)$, but it works like magic.}
|
||||
{cpp}
|
||||
{source/Graph/MCMF.cpp}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\section{Tree}
|
||||
|
||||
\Algorithm{HLD(Heavy Light Decomposition)}
|
||||
{}
|
||||
{}
|
||||
{cpp}
|
||||
{source/Tree/HLD.cpp}
|
||||
|
||||
\Algorithm{Centroid Tree}
|
||||
{}
|
||||
{}
|
||||
{cpp}
|
||||
{source/Tree/Centroid.cpp}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\section{Data Structure}
|
||||
|
||||
\Algorithm{PBDS - Policy-Based Data Structure}
|
||||
{}
|
||||
{Equivalent to std::set}
|
||||
{cpp}
|
||||
{source/DS/PBDS.cpp}
|
||||
|
||||
\Algorithm{rope}{}{}{cpp}{}
|
||||
|
||||
\Algorithm{Union and Find - Queue Undoing}
|
||||
{}
|
||||
{$\mathcal O(\log^2N)$}
|
||||
{cpp}
|
||||
{source/DS/UF_QUndo.cpp}
|
||||
|
||||
\Algorithm{Fenwick Tree}{}{}{cpp}
|
||||
{source/DS/Fenwick.cpp}
|
||||
|
||||
\Algorithm{Segment Tree Generalization}
|
||||
{}
|
||||
{$\mathcal O(\log N)$}
|
||||
{cpp}
|
||||
{source/DS/SegmentTree.cpp}
|
||||
|
||||
\Algorithm{Li-Chao Tree}
|
||||
{}
|
||||
{}
|
||||
{cpp}
|
||||
{source/DS/LiChaoTree.cpp}
|
||||
|
||||
\Algorithm{Splay Tree}
|
||||
{}
|
||||
{}
|
||||
{cpp}
|
||||
{source/DS/SplayTree.cpp}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\section{Numerical Analysis}
|
||||
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\section{Technic}
|
||||
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\section{Misc}
|
||||
|
||||
\Algorithm{Fast Input}
|
||||
{Fast Input with fread. Do not use with scanf, cin, or other input function. Use \texttt{forr(i, n) read(arr[i]);} instead of \texttt{forr(i, n) scanf("\%d", arr+i);}. Use \texttt{read(s+1)} instead of \texttt{scanf("\%s", s+1);}.}
|
||||
{}
|
||||
{cpp}
|
||||
{source/Misc/FastI.cpp}
|
||||
|
||||
\Algorithm{MT19937 Random Number}
|
||||
{}
|
||||
{}
|
||||
{cpp}
|
||||
{source/Misc/mt19937.cpp}
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\begin{center}
|
||||
\bigskip
|
||||
--- Document end ---
|
||||
\end{center}
|
||||
|
||||
\end{multicols}
|
||||
|
||||
\end{document}
|
||||
12
2025spring/source/DP/DnC.cpp
Normal file
12
2025spring/source/DP/DnC.cpp
Normal file
@@ -0,0 +1,12 @@
|
||||
//D[t][s...e]를 구해야 하고, j의 탐색 범위는 [l, r]
|
||||
void f(int t, int s, int e, int l, int r){
|
||||
if(s > e) return;
|
||||
int m = s + e >> 1;
|
||||
int opt = l;
|
||||
for(int i=l; i<=r; i++){
|
||||
if(D[t-1][opt] + C[opt][m] > D[t-1][i] + C[i][m]) opt = i;
|
||||
}
|
||||
D[t][m] = D[t-1][opt] + C[opt][m];
|
||||
f(t, s, m-1, l, opt);
|
||||
f(t, m+1, e, opt, r);
|
||||
}
|
||||
17
2025spring/source/DP/LIS.cpp
Normal file
17
2025spring/source/DP/LIS.cpp
Normal file
@@ -0,0 +1,17 @@
|
||||
template<class I> vi lis(const vector<I>& S) {
|
||||
if (S.empty()) return {};
|
||||
vi prev(sz(S));
|
||||
typedef pair<I, int> p;
|
||||
vector<p> res;
|
||||
rep(i,0,sz(S)) {
|
||||
// change 0 -> i for longest non-decreasing subsequence
|
||||
auto it = lower_bound(all(res), p{S[i], 0});
|
||||
if (it == res.end()) res.emplace_back(), it = res.end()-1;
|
||||
*it = {S[i], i};
|
||||
prev[i] = it == res.begin() ? 0 : (it-1)->second;
|
||||
}
|
||||
int L = sz(res), cur = res.back().second;
|
||||
vi ans(L);
|
||||
while (L--) ans[L] = cur, cur = prev[cur];
|
||||
return ans;
|
||||
}
|
||||
30
2025spring/source/DP/LineContainer.cpp
Normal file
30
2025spring/source/DP/LineContainer.cpp
Normal file
@@ -0,0 +1,30 @@
|
||||
struct Line {
|
||||
mutable ll k, m, p;
|
||||
bool operator<(const Line& o) const { return k < o.k; }
|
||||
bool operator<(ll x) const { return p < x; }
|
||||
};
|
||||
|
||||
struct LineContainer : multiset<Line, less<>> {
|
||||
// (for doubles, use inf = 1/.0, div(a,b) = a/b)
|
||||
static const ll inf = LLONG_MAX;
|
||||
ll div(ll a, ll b) { // floored division
|
||||
return a / b - ((a ^ b) < 0 && a % b); }
|
||||
bool isect(iterator x, iterator y) {
|
||||
if (y == end()) return x->p = inf, 0;
|
||||
if (x->k == y->k) x->p = x->m > y->m ? inf : -inf;
|
||||
else x->p = div(y->m - x->m, x->k - y->k);
|
||||
return x->p >= y->p;
|
||||
}
|
||||
void add(ll k, ll m) {
|
||||
auto z = insert({k, m, 0}), y = z++, x = y;
|
||||
while (isect(y, z)) z = erase(z);
|
||||
if (x != begin() && isect(--x, y)) isect(x, y = erase(y));
|
||||
while ((y = x) != begin() && (--x)->p >= y->p)
|
||||
isect(x, erase(y));
|
||||
}
|
||||
ll query(ll x) {
|
||||
assert(!empty());
|
||||
auto l = *lower_bound(x);
|
||||
return l.k * x + l.m;
|
||||
}
|
||||
};
|
||||
52
2025spring/source/DP/SlopeTrick.cpp
Normal file
52
2025spring/source/DP/SlopeTrick.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
const int N = 1e6+7;
|
||||
int arr[N];
|
||||
priority_queue<int> pq;
|
||||
ll ans = 0;
|
||||
int main()
|
||||
{
|
||||
getint(n);
|
||||
forr(i, n) scanf("%d", arr+i);
|
||||
|
||||
pq.push(arr[1]); int t=0; ll val = 0;
|
||||
fors(i, 2, n)
|
||||
{
|
||||
t++;
|
||||
int r = t + pq.top();
|
||||
if(r <= arr[i]) pq.push(arr[i]-t);
|
||||
else
|
||||
{
|
||||
pq.push(arr[i]-t); pq.push(arr[i]-t); pq.pop();
|
||||
ans += r-arr[i];
|
||||
}
|
||||
}
|
||||
|
||||
printf("%lld", ans);
|
||||
}
|
||||
|
||||
|
||||
int arr[N];
|
||||
priority_queue<int> pq;
|
||||
int ans2[N];
|
||||
int main()
|
||||
{
|
||||
getint(n);
|
||||
forr(i, n) scanf("%d", arr+i);
|
||||
|
||||
pq.push(arr[1]); ll ans = 0;
|
||||
ans2[1] = arr[1];
|
||||
fors(i, 2, n)
|
||||
{
|
||||
int r = (i-1) + pq.top();
|
||||
if(r <= arr[i]) pq.push(arr[i]-(i-1));
|
||||
else
|
||||
{
|
||||
pq.push(arr[i]-(i-1)); pq.push(arr[i]-(i-1)); pq.pop();
|
||||
ans += r-arr[i];
|
||||
}
|
||||
|
||||
ans2[i] = pq.top() + (i-1);
|
||||
}
|
||||
|
||||
fore(i, n-1, 1) ans2[i] = min(ans2[i], ans2[i+1]-1);
|
||||
forr(i, n) printf("%d\n", ans2[i]);
|
||||
}
|
||||
22
2025spring/source/DP/SoS.cpp
Normal file
22
2025spring/source/DP/SoS.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
int n = 20;
|
||||
vector<int> a(1 << n);
|
||||
|
||||
// keeps track of the sum over subsets
|
||||
// with a certain amount of matching bits in the prefix
|
||||
vector<vector<int>> dp(1 << n, vector<int>(n));
|
||||
|
||||
vector<int> sos(1 << n);
|
||||
for (int mask = 0; mask < (1 << n); mask++) {
|
||||
dp[mask][-1] = a[mask];
|
||||
for (int x = 0; x < n; x++) {
|
||||
dp[mask][x] = dp[mask][x - 1];
|
||||
if (mask & (1 << x)) { dp[mask][x] += dp[mask - (1 << x)][x - 1]; }
|
||||
}
|
||||
sos[mask] = dp[mask][n - 1];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////
|
||||
D[i]에 미리 i에 해당하는 값을 넣어둔다
|
||||
fors(d, 0, 19) fors(i,0,(1<<20)-1)
|
||||
if(i & (1<<d)) D[i] += D[i^(1<<d)];
|
||||
-> D[i] : sum of subset of mask i
|
||||
9
2025spring/source/DS/Fenwick.cpp
Normal file
9
2025spring/source/DS/Fenwick.cpp
Normal file
@@ -0,0 +1,9 @@
|
||||
ll tree[N];
|
||||
void update(int i,ll x) {
|
||||
while(i < N) tree[i] += x, i += i&-i;
|
||||
}
|
||||
int query(int i) {
|
||||
ll s = 0;
|
||||
while(i) s += tree[i], i -= i&-i;
|
||||
return s;
|
||||
}
|
||||
69
2025spring/source/DS/LiChaoTree.cpp
Normal file
69
2025spring/source/DS/LiChaoTree.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
struct Line
|
||||
{
|
||||
ll a=0, b=(ll)2e18+7;
|
||||
ll operator()(ll x){return a*x+b;}
|
||||
Line():a(0),b((ll)2e18+7){}
|
||||
Line(ll a, ll b):a(a), b(b){}
|
||||
};
|
||||
|
||||
ll middle(ll s, ll e){return (s+e+(ll)2e18)/2-(ll)1e18;}
|
||||
struct Node {
|
||||
Node *l=0, *r=0;
|
||||
Line v;
|
||||
Node():l(0), r(0), v(Line()){}
|
||||
};
|
||||
void insert(Node* node, Line v, ll l, ll r, ll s, ll e) {
|
||||
ll mid=middle(s, e);
|
||||
if(e < l or r < s) return;
|
||||
if(s == e) {
|
||||
node->v = (node->v(s) < v(s))?node->v:v;
|
||||
return;
|
||||
}
|
||||
if(!node->l) node->l = new Node();
|
||||
if(!node->r) node->r = new Node();
|
||||
|
||||
if(l <= s and e <= r) {
|
||||
if(node->v(s) >= v(s) and node->v(e) >= v(e)){node->v = v; return;}
|
||||
if(node->v(s) <= v(s) and node->v(e) <= v(e)) return;
|
||||
insert(node->l, v, l, r, s, mid);
|
||||
insert(node->r, v, l, r, mid+1, e);
|
||||
}
|
||||
else {
|
||||
insert(node->l, v, l, r, s, mid);
|
||||
insert(node->r, v, l, r, mid+1, e);
|
||||
}
|
||||
}
|
||||
ll query(Node* node, ll x, ll s, ll e)
|
||||
{
|
||||
if(!node) return (ll)2e18+7;
|
||||
if(x < s or e < x) return (ll)2e18+7;
|
||||
if(s == e) return node->v(x);
|
||||
|
||||
ll mid = middle(s, e);
|
||||
return min({query(node->l, x, s,mid), query(node->r, x, mid+1, e), node->v(x)});
|
||||
}
|
||||
// 전체 구간을 미리 고정해 놓아야 함.
|
||||
// (const int L = -1e9, R = 1e9);
|
||||
// Insert : insert(root, Line 객체, l, r, L, R);
|
||||
// Query : query(root, x, L, R);
|
||||
int main() {
|
||||
Node *root = new Node();
|
||||
getint(n); getint(Q);
|
||||
forr(i, n) {
|
||||
getll(l); getll(r); getll(a); getll(b);
|
||||
insert(root, Line(a,b), l,r-1,(ll)-1e9-7, (ll)1e9+7);
|
||||
}
|
||||
while(Q--) {
|
||||
getint(q);
|
||||
if(q == 0) {
|
||||
getll(l); getll(r); getll(a); getll(b);
|
||||
insert(root, Line(a,b), l,r-1,(ll)-1e9-7, (ll)1e9+7);
|
||||
}
|
||||
if(q == 1) {
|
||||
getll(x);
|
||||
ll ans = query(root, x,(ll)-1e9-7, (ll)1e9+7);
|
||||
if(ans == (ll)2e18+7) printf("INFINITY\n");
|
||||
else printf("%lld\n", ans);
|
||||
}
|
||||
}
|
||||
}
|
||||
37
2025spring/source/DS/PBDS.cpp
Normal file
37
2025spring/source/DS/PBDS.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
#include <bits/stdc++.h>
|
||||
#include <ext/rope>
|
||||
#include <ext/pb_ds/assoc_container.hpp>
|
||||
#include <ext/pb_ds/tree_policy.hpp>
|
||||
using namespace __gnu_pbds;
|
||||
using namespace __gnu_cxx;
|
||||
|
||||
template<typename T>
|
||||
using indexed_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
|
||||
|
||||
indexed_set<int> s;
|
||||
s.insert(3); s.insert(2); s.insert(3); s.insert(9); s.insert(7); //2 3 7 9
|
||||
s.insert(5); //2 3 5 7 9
|
||||
s.erase(5); //2 3 7 9
|
||||
|
||||
auto x = s.find_by_order(2); // *x : 7
|
||||
|
||||
s.order_of_key(6) // 2
|
||||
s.order_of_key(7) // 2
|
||||
s.order_of_key(8) // 3
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// greater_equal <- ordered_multiset / greater <- ordered_multiset
|
||||
#define oset_greater tree<ll, null_type, greater_equal<ll>, rb_tree_tag, tree_order_statistics_node_update>
|
||||
#define oset_less tree<ll, null_type, less_equal<ll>, rb_tree_tag, tree_order_statistics_node_update>
|
||||
|
||||
void oset_m_erase(ordered_set_greater &OS, ll val){
|
||||
int index = OS.order_of_key(val);
|
||||
oset_greater::iterator it = OS.find_by_order(index);
|
||||
if(it != OS.end() && *it == val) OS.erase(it);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
rope<ll> r;
|
||||
r.insert(r.size() - t, i); //r.size()-t번째 자리에 i를 삽입
|
||||
r.substr(a, b - a + 1) // a부터 (b-a+1)개 만큼을 잘라낸다. 즉, [a, b] 선택
|
||||
160
2025spring/source/DS/SegmentTree.cpp
Normal file
160
2025spring/source/DS/SegmentTree.cpp
Normal file
@@ -0,0 +1,160 @@
|
||||
namespace GMS
|
||||
{
|
||||
template<typename D, D (*join)(D,D), D _e>
|
||||
class Segtree {
|
||||
class Node {
|
||||
Node *l, *r;
|
||||
int s,e; D v;
|
||||
public:
|
||||
Node(int s, int e) :l(0), r(0), s(s), e(e), v(_e){};
|
||||
~Node(){delete l; delete r;}
|
||||
|
||||
template<typename Dini>
|
||||
friend void init(Node* node, Dini arr[] = NULL) {
|
||||
int s = node->s, e=node->e, mid=(s+e)/2;
|
||||
if(s == e) {
|
||||
node->v = D(arr?arr[s]:_e);
|
||||
return;
|
||||
}
|
||||
|
||||
node->l = new Node(s, mid);
|
||||
init(node->l, arr);
|
||||
node->r = new Node(mid+1, e);
|
||||
init(node->r, arr);
|
||||
|
||||
node->v = join(node->l->v, node->r->v);
|
||||
}
|
||||
friend D _query(Node* node, int a, int b) {
|
||||
int s=node->s, e=node->e;
|
||||
if(a <= s and e <= b) return node->v;
|
||||
if(b < s or e < a) return _e;
|
||||
|
||||
return join(_query(node->l, a, b), _query(node->r, a, b));
|
||||
}
|
||||
friend void _update
|
||||
(Node* node, int i, function<D(D)> upd) {
|
||||
int s=node->s, e=node->e;
|
||||
if(i < s or e < i) return;
|
||||
if(s == e)
|
||||
{
|
||||
node->v = upd(node->v);
|
||||
return;
|
||||
}
|
||||
|
||||
_update(node->l, i, upd);
|
||||
_update(node->r, i, upd);
|
||||
|
||||
node->v = join(node->l->v, node->r->v);
|
||||
}
|
||||
};
|
||||
|
||||
Node *root;
|
||||
public:
|
||||
template<typename Dini>
|
||||
Segtree(int s,int e, Dini arr[] = NULL) {
|
||||
root = new Node(s, e);
|
||||
init(root, arr);
|
||||
}
|
||||
~Segtree(){delete root;}
|
||||
D query(int s, int e)
|
||||
{return _query(root, s, e);}
|
||||
void update(int i, function<D(D)> upd)
|
||||
{_update(root, i, upd);}
|
||||
};
|
||||
|
||||
|
||||
template<typename D, D (*join)(D,D), D _e, typename L, D (*apply)(D, L, int), L (*give)(L, L), L _l>
|
||||
class LZSegtree {
|
||||
class Node {
|
||||
Node *l, *r;
|
||||
int s,e;
|
||||
D v; L lz;
|
||||
|
||||
void prop() {
|
||||
v = apply(v, lz, e-s+1);
|
||||
if(l) l->lz = give(l->lz, lz);
|
||||
if(r) r->lz = give(r->lz, lz);
|
||||
|
||||
lz = _l;
|
||||
}
|
||||
|
||||
public:
|
||||
Node(int s, int e)
|
||||
:l(0), r(0), s(s), e(e), v(_e), lz(_l){};
|
||||
~Node(){delete l; delete r;}
|
||||
|
||||
template<typename Dini>
|
||||
friend void init(Node* node, Dini arr[] = NULL) {
|
||||
int s = node->s, e=node->e, mid=(s+e)/2;
|
||||
if(s == e)
|
||||
{
|
||||
node->v = D(arr?arr[s]:_e);
|
||||
return;
|
||||
}
|
||||
|
||||
node->l = new Node(s, mid);
|
||||
init(node->l, arr);
|
||||
node->r = new Node(mid+1, e);
|
||||
init(node->r, arr);
|
||||
|
||||
node->v = join(node->l->v, node->r->v);
|
||||
}
|
||||
friend D _query(Node* node, int a, int b) {
|
||||
node->prop();
|
||||
int s=node->s, e=node->e;
|
||||
if(a <= s and e <= b) return node->v;
|
||||
if(b < s or e < a) return _e;
|
||||
|
||||
return join(_query(node->l, a, b), _query(node->r, a, b));
|
||||
}
|
||||
friend void _update
|
||||
(Node* node, int a, int b, function<L(L)> upd){
|
||||
node->prop();
|
||||
int s=node->s, e=node->e;
|
||||
if(b < s or e < a) return;
|
||||
if(a <= s and e <= b)
|
||||
{
|
||||
node->lz = upd(node->lz);
|
||||
node->prop();
|
||||
return;
|
||||
}
|
||||
|
||||
_update(node->l, a, b, upd);
|
||||
_update(node->r, a, b, upd);
|
||||
|
||||
node->v = join(node->l->v, node->r->v);
|
||||
}
|
||||
};
|
||||
|
||||
Node *root;
|
||||
public:
|
||||
template<typename Dini>
|
||||
LZSegtree(int s,int e, Dini arr[] = NULL)
|
||||
{
|
||||
root = new Node(s, e);
|
||||
init(root, arr);
|
||||
}
|
||||
~LZSegtree(){delete root;}
|
||||
D query(int s, int e){return _query(root, s, e);}
|
||||
void update(int s, int e, function<L(L)> upd){_update(root, s, e, upd);}
|
||||
};
|
||||
} // namespace GMS
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
#define data _data
|
||||
|
||||
struct data {
|
||||
int m, m_cnt;
|
||||
constexpr data(int m):m(m), m_cnt(1){}
|
||||
constexpr data(int m, int m_cnt):m(m), m_cnt(m_cnt){}
|
||||
};
|
||||
data join(data A, data B) {
|
||||
if(A.m == B.m) return data(A.m, A.m_cnt+B.m_cnt);
|
||||
if(A.m < B.m) return A;
|
||||
else return B;
|
||||
}
|
||||
data apply(data A, int lz, int len)
|
||||
{return {A.m+lz, A.m_cnt};}
|
||||
int give(int a, int b){return a+b;}
|
||||
|
||||
using Seg = GMS::LZSegtree<data, join, {(int)1e9, 0}, int, apply, give, 0>;
|
||||
174
2025spring/source/DS/SplayTree.cpp
Normal file
174
2025spring/source/DS/SplayTree.cpp
Normal file
@@ -0,0 +1,174 @@
|
||||
struct Node
|
||||
{
|
||||
Node *p, *l, *r;
|
||||
int cnt;
|
||||
ll val; ll m, M, sum; ll lazy;
|
||||
bool flip; bool dum;
|
||||
|
||||
Node(ll val, bool dum = false):p(0),l(0), r(0), cnt(1), val(val), m(val), M(val), sum(val), lazy(0), flip(0), dum(dum){}
|
||||
|
||||
void fix(){
|
||||
cnt = 1+(l?l->cnt:0)+(r?r->cnt:0);
|
||||
sum = val+(l?l->sum:0)+(r?r->sum:0);
|
||||
m = min({val, (l?l->m:inf), (r?r->m:inf)});
|
||||
M = max({val, (l?l->M:-1), (r?r->M:-1)});
|
||||
}
|
||||
void prop(){
|
||||
if(flip){
|
||||
swap(l, r);
|
||||
if(l) l->flip = !l->flip;
|
||||
if(r) r->flip = !r->flip;
|
||||
|
||||
flip = false;
|
||||
}
|
||||
if(lazy){
|
||||
val += lazy; sum += cnt * lazy;
|
||||
if(l) l->lazy += lazy;
|
||||
if(r) r->lazy += lazy;
|
||||
|
||||
lazy = 0;
|
||||
}
|
||||
}
|
||||
|
||||
} *root;
|
||||
|
||||
// 자기보다 더 높은 노드를 루트로 하는 SplayTree를 조작하는 경우, 하위 SplayTree는 unvalid된다.
|
||||
struct SplayTree{
|
||||
Node *root = NULL, *rp = NULL;
|
||||
|
||||
SplayTree(){}
|
||||
SplayTree(Node *rt){
|
||||
if(!rt) return;
|
||||
|
||||
root = rt;
|
||||
rp = rt->p;
|
||||
}
|
||||
|
||||
void mop(Node *node){
|
||||
if(node == root) node->prop();
|
||||
else mop(node->p);
|
||||
|
||||
if(node->l) node->l->prop();
|
||||
if(node->r) node->r->prop();
|
||||
}
|
||||
|
||||
void rotate(Node *node){
|
||||
if(!root) return;
|
||||
|
||||
if(node->p == rp) return;
|
||||
if(node->p->l == node){
|
||||
Node *p = node->p, *g = p->p;
|
||||
Node *a = node->l, *b = node->r, *c = p->r;
|
||||
|
||||
p->l = b; if(b) b->p = p;
|
||||
p->r = c; if(c) c->p = p;
|
||||
|
||||
node->l = a; if(a) a->p = node;
|
||||
node->r = p; p->p = node;
|
||||
|
||||
node->p = g; if(g) (g->l == p?g->l:g->r) = node;
|
||||
|
||||
p->fix(); node->fix();
|
||||
|
||||
if(p == root) root = node;
|
||||
}
|
||||
else{
|
||||
Node *p = node->p, *g = p->p;
|
||||
Node *a = p->l, *b = node->l, *c = node->r;
|
||||
|
||||
p->l = a; if(a) a->p = p;
|
||||
p->r = b; if(b) b->p = p;
|
||||
|
||||
node->l = p; p->p = node;
|
||||
node->r = c; if(c) c->p = node;
|
||||
|
||||
node->p = g; if(g) (g->l == p?g->l:g->r) = node;
|
||||
|
||||
p->fix(); node->fix();
|
||||
|
||||
if(p == root) root = node;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void splay(Node* node){
|
||||
if(!root) return;
|
||||
assert(node); mop(node);
|
||||
|
||||
while(node->p != rp){
|
||||
Node *p, *g;
|
||||
p = node->p; g = p->p;
|
||||
|
||||
if(g == rp) rotate(node);
|
||||
else if((p->l == node) == (g->l == p)) rotate(p), rotate(node);
|
||||
else rotate(node), rotate(node);
|
||||
}
|
||||
|
||||
root = node;
|
||||
}
|
||||
|
||||
Node* insert(ll val, bool dum = false){
|
||||
if(!root){
|
||||
root = new Node(val, dum);
|
||||
return root;
|
||||
}
|
||||
else{
|
||||
Node *now = root;
|
||||
while(now->r) now = now->r;
|
||||
Node* ret = now->r = new Node(val, dum);
|
||||
now->r->p = now;
|
||||
|
||||
splay(ret); return ret;
|
||||
}
|
||||
}
|
||||
|
||||
Node* find_kth(int k) { // 0-indexed
|
||||
assert(root);
|
||||
assert(root->cnt > k);
|
||||
Node *now = root; now->prop();
|
||||
while(true){
|
||||
while(now->l and now->l->cnt > k) now = now->l, now->prop();
|
||||
k -= now->l?now->l->cnt:0;
|
||||
|
||||
if(k == 0) break;
|
||||
k--; now = now->r;
|
||||
now->prop();
|
||||
}
|
||||
|
||||
splay(now);
|
||||
return now;
|
||||
}
|
||||
// s-1, e+1번째 노드가 항상 존재해야 한다.
|
||||
Node* gather(int s, int e){
|
||||
find_kth(e+1);
|
||||
SplayTree(root->l).find_kth(s-1);
|
||||
|
||||
assert(root->l->r);
|
||||
return root->l->r;
|
||||
}
|
||||
void update(int i, int j, ll val){
|
||||
Node *node = gather(i, j);
|
||||
|
||||
node->lazy += val; node->prop();
|
||||
node->p->fix(); node->p->p->fix();
|
||||
}
|
||||
void reverse(int i, int j){
|
||||
Node *node = gather(i, j);
|
||||
node->flip = !node->flip;
|
||||
}
|
||||
|
||||
void p_vals(){p_vals(root, 0, false);}
|
||||
void p_vals(Node* node, ll lz, bool flip){
|
||||
lz += node->lazy; flip ^= node->flip;
|
||||
if(!flip){
|
||||
if(node->l) p_vals(node->l, lz, flip);
|
||||
if(!node->dum) printf("%lld ", node->val+lz);
|
||||
if(node->r) p_vals(node->r, lz, flip);
|
||||
}
|
||||
else{
|
||||
if(node->r) p_vals(node->r, lz, flip);
|
||||
if(!node->dum) printf("%lld ", node->val+lz);
|
||||
if(node->l) p_vals(node->l, lz, flip);
|
||||
}
|
||||
}
|
||||
};
|
||||
60
2025spring/source/DS/UF_QUndo.cpp
Normal file
60
2025spring/source/DS/UF_QUndo.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
struct dsu_pb {
|
||||
const int N;
|
||||
vi par; stack<pair<pii, pii> > s;
|
||||
|
||||
dsu_pb(int N):N(N), par(N) {
|
||||
fors(i, 0, N-1) par[i] = -1;
|
||||
}
|
||||
int root(int i) {
|
||||
if(par[i] < 0) return i;
|
||||
return root(par[i]);
|
||||
}
|
||||
bool join(int i, int j) {
|
||||
i = root(i); j = root(j);
|
||||
s.push({{i, par[i]}, {j, par[j]}});
|
||||
if(i == j) return false;
|
||||
if(-par[i] < -par[j]) swap(i, j);
|
||||
par[i] += par[j]; par[j] = i;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
void unjoin() {
|
||||
assert(!s.empty());
|
||||
auto [i, j] = s.top(); s.pop();
|
||||
par[i.fi] = i.se; par[j.fi] = j.se;
|
||||
}
|
||||
};
|
||||
|
||||
struct dsu_pf : public dsu_pb {
|
||||
vector<pair<bool, pii> > st; // fi==0 -> B type, fi==1 -> A type
|
||||
vector<pair<bool, pii> > tmp[2];
|
||||
int A=0, B=0;
|
||||
dsu_pf(int N):dsu_pb(N){}
|
||||
|
||||
bool join(int i, int j) {
|
||||
st.pb({0, {i, j}}); B++;
|
||||
return dsu_pb::join(i, j);
|
||||
}
|
||||
void pop_front() {
|
||||
assert(!st.empty());
|
||||
if(A == 0) {
|
||||
forr(i, B) unjoin();
|
||||
A = B; B = 0; reverse(all(st));
|
||||
for(auto &[b, p]:st) b = 1, dsu_pb::join(p.fi, p.se);
|
||||
}
|
||||
else if(st.back().fi == false) {
|
||||
tmp[st.back().fi].pb(st.back()); st.pop_back(); unjoin();
|
||||
while(tmp[0].size() != tmp[1].size() and (unsigned) A != tmp[1].size()) {
|
||||
tmp[st.back().fi].pb(st.back());
|
||||
st.pop_back();
|
||||
unjoin();
|
||||
}
|
||||
for(auto i:{0, 1}) reverse(all(tmp[i]));
|
||||
for(auto i:{0, 1}) for(auto v:tmp[i])
|
||||
st.pb(v), dsu_pb::join(v.se.fi, v.se.se);
|
||||
tmp[0].clear(); tmp[1].clear();
|
||||
}
|
||||
A--; st.pop_back(); unjoin();
|
||||
}
|
||||
};
|
||||
22
2025spring/source/Fundemental.cpp
Normal file
22
2025spring/source/Fundemental.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
#include <bits/stdc++.h>
|
||||
|
||||
#define getint(n) int n; scanf("%d%*c", &n)
|
||||
#define getll(n) long long n; scanf("%lld%*c", &n)
|
||||
#define getchar(n) char n; scanf("%c%*c", &n);
|
||||
#define intab getint(a); getint(b)
|
||||
|
||||
#define forr(i, n) for(int i=1;i<=(n);i++)
|
||||
#define fors(i, s, e) for(int i=(s); i<=(e); i++)
|
||||
#define fore(i, e, s) for(int i=(e); i>=(s); i--)
|
||||
|
||||
#define fi first
|
||||
#define se second
|
||||
#define all(v) (v).begin(), (v).end()
|
||||
#define rall(v) (v).rbegin(), (v).rend()
|
||||
#define pb push_back
|
||||
|
||||
using namespace std;
|
||||
using ll = long long; using lll = __int128_t;
|
||||
using pii = pair<int,int>; using pll = pair<ll,ll>;
|
||||
using vi = vector<int>; using vl = vector<ll>;
|
||||
using vii = vector<pii>; using vll = vector<pll>;
|
||||
47
2025spring/source/Geometry/Mindset.cpp
Normal file
47
2025spring/source/Geometry/Mindset.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
using pii=pair<int,int>;
|
||||
pii operator+(pii A, pii B){return {A.fi+B.fi, A.se+B.se};}
|
||||
pii operator-(pii A, pii B){return {A.fi-B.fi, A.se-B.se};}
|
||||
ll operator*(pii A, pii B){return (ll)A.fi*B.fi+(ll)A.se*B.se;} // inner product
|
||||
ll operator/(pii A, pii B){return (ll)A.fi*B.se-(ll)A.se*B.fi;} // outer product
|
||||
|
||||
// 각도 정렬 (O = pii(0, 0))
|
||||
sort(P+1, P+1+n, [](pii A, pii B) {
|
||||
if(B == O) return false;
|
||||
if(A == O) return true;
|
||||
return (A<O)!=(B<O)?A>B:A/B<0;
|
||||
});
|
||||
|
||||
// 선분 교차
|
||||
// Segment : fi에서 시작하는 se 벡터
|
||||
// fi + k * se, 0 <= k <= 1
|
||||
|
||||
using Segment = pair<pii, pii>;
|
||||
int isJoin(const Segment& A, const Segment& B) {
|
||||
if(B.se/A.se != 0) {
|
||||
ll p = (A.fi-B.fi)/A.se;
|
||||
ll q = B.se/A.se;
|
||||
|
||||
if(q<0) q = -q, p = -p;
|
||||
if(p < 0 or p > q) return false;
|
||||
|
||||
p = (B.fi-A.fi)/B.se;
|
||||
q = A.se/B.se;
|
||||
|
||||
if(q<0) q = -q, p = -p;
|
||||
if(p < 0 or p > q) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
if((A.fi-B.fi)/A.se != 0) return false;
|
||||
|
||||
ll p = A.fi*A.se, q = (A.fi+A.se)*A.se;
|
||||
ll r = B.fi*A.se, s = (B.fi+B.se)*A.se;
|
||||
|
||||
if(p>q) swap(p, q); if(r>s) swap(r, s);
|
||||
|
||||
if(max(p, r) > min(q, s)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
16
2025spring/source/Geometry/PointInConvexPolygon.cpp
Normal file
16
2025spring/source/Geometry/PointInConvexPolygon.cpp
Normal file
@@ -0,0 +1,16 @@
|
||||
auto isunder = [](pii upper[], int u, pii x, bool inv = false){ // inv==true : isover
|
||||
int r = inv?-1:1;
|
||||
int idx = lower_bound(upper+1, upper+1+u, x,
|
||||
[&r](pii a, pii b){return r*a.fi<r*b.fi;}) - upper;
|
||||
if(idx > u) return false;
|
||||
if(idx == 1) {
|
||||
if(r*x.fi < r*upper[1].fi) return false;
|
||||
else {
|
||||
int h = upper[1].se;
|
||||
if(upper[2].fi == upper[1].fi) h = upper[2].se;
|
||||
|
||||
return r*x.se <= r*h;
|
||||
}
|
||||
}
|
||||
return ccw(upper[idx-1], upper[idx], x) <= 0;
|
||||
};
|
||||
163
2025spring/source/Geometry/geometry_kaere.cpp
Normal file
163
2025spring/source/Geometry/geometry_kaere.cpp
Normal file
@@ -0,0 +1,163 @@
|
||||
typedef pair<ll, ll> pll;
|
||||
#define _x first
|
||||
#define _y second
|
||||
|
||||
pll operator-(const pll &a, const pll &b){
|
||||
return {a._x - b._x, a._y - b._y};
|
||||
}
|
||||
|
||||
ll cross(const pll &a, const pll &b){
|
||||
return a._x * b._y - b._x * a._y;
|
||||
}
|
||||
|
||||
ll dot(const pll &a, const pll &b){
|
||||
return a._x * b._x + a._y * b._y;
|
||||
}
|
||||
|
||||
int ccw(const pll &p1, const pll &p2, const pll &p3){
|
||||
ll res = cross(p2 - p1, p3 - p1);
|
||||
return (res != 0) * (res < 0 ? -1 : 1);
|
||||
}
|
||||
|
||||
// dist of point - point
|
||||
double dist(const pll &p1, const pll &p2){
|
||||
return sqrt((p1._x - p2._x) * (p1._x - p2._x) + (p1._y - p2._y) * (p1._y - p2._y));
|
||||
}
|
||||
|
||||
// dist of line - point
|
||||
double dist(const pll &l1, const pll &l2, const pll &p){
|
||||
ll area = abs(cross(l2 - l1, p - l1));
|
||||
return area / dist(l1, l2);
|
||||
}
|
||||
|
||||
// dist of seg - point
|
||||
double segDist(P& s, P& e, P& p) {
|
||||
if (s==e) return (p-s).dist();
|
||||
auto d = (e-s).dist2(), t = min(d,max(.0,(p-s).dot(e-s)));
|
||||
return ((p-s)*d-(e-s)*t).dist()/d;
|
||||
}
|
||||
|
||||
P perp() const { return P(-y, x); } // rotates +90 degrees
|
||||
int sgn(T x) { return (x > 0) - (x < 0); } // sign of x
|
||||
|
||||
// Returns where p is as seen from s towards e. 1/0/-1 <-> left/on line/right.
|
||||
int sideOf(P s, P e, P p) { return sgn(s.cross(e, p)); }
|
||||
|
||||
// Returns a vector of either 0, 1, or 2 intersection points.
|
||||
template<class P>
|
||||
vector<P> circleLine(P c, double r, P a, P b) {
|
||||
P ab = b - a, p = a + ab * (c-a).dot(ab) / ab.dist2();
|
||||
double s = a.cross(b, c), h2 = r*r - s*s / ab.dist2();
|
||||
if (h2 < 0) return {};
|
||||
if (h2 == 0) return {p};
|
||||
P h = ab.unit() * sqrt(h2);
|
||||
return {p - h, p + h};
|
||||
}
|
||||
|
||||
// Computes the pair of points at which two circles intersect.
|
||||
typedef Point<double> P;
|
||||
bool circleInter(P a,P b,double r1,double r2,pair<P, P>* out) {
|
||||
if (a == b) { assert(r1 != r2); return false; }
|
||||
P vec = b - a;
|
||||
double d2 = vec.dist2(), sum = r1+r2, dif = r1-r2,
|
||||
p = (d2 + r1*r1 - r2*r2)/(d2*2), h2 = r1*r1 - p*p*d2;
|
||||
if (sum*sum < d2 || dif*dif > d2) return false;
|
||||
P mid = a + vec*p, per = vec.perp() * sqrt(fmax(0, h2) / d2);
|
||||
*out = {mid + per, mid - per};
|
||||
return true;
|
||||
}
|
||||
|
||||
// Returns true iff p lies on the line segment from s to e.
|
||||
template<class P> bool onSegment(P s, P e, P p) {
|
||||
return p.cross(s, e) == 0 && (s - p).dot(e - p) <= 0;
|
||||
}
|
||||
|
||||
// Circumcircle
|
||||
typedef Point<double> P;
|
||||
double ccRadius(const P& A, const P& B, const P& C) {
|
||||
return (B-A).dist()*(C-B).dist()*(A-C).dist()/
|
||||
abs((B-A).cross(C-A))/2;
|
||||
}
|
||||
P ccCenter(const P& A, const P& B, const P& C) {
|
||||
P b = C-A, c = B-A;
|
||||
return A + (b*c.dist2()-c*b.dist2()).perp()/b.cross(c)/2;
|
||||
}
|
||||
|
||||
// Minimum enclosing circle
|
||||
pair<P, double> mec(vector<P> ps) {
|
||||
shuffle(all(ps), mt19937(time(0)));
|
||||
P o = ps[0];
|
||||
double r = 0, EPS = 1 + 1e-8;
|
||||
rep(i,0,sz(ps)) if ((o - ps[i]).dist() > r * EPS) {
|
||||
o = ps[i], r = 0;
|
||||
rep(j,0,i) if ((o - ps[j]).dist() > r * EPS) {
|
||||
o = (ps[i] + ps[j]) / 2;
|
||||
r = (o - ps[i]).dist();
|
||||
rep(k,0,j) if ((o - ps[k]).dist() > r * EPS) {
|
||||
o = ccCenter(ps[i], ps[j], ps[k]);
|
||||
r = (o - ps[i]).dist();
|
||||
}
|
||||
}
|
||||
}
|
||||
return {o, r};
|
||||
}
|
||||
|
||||
// point inside convex hull in logN
|
||||
bool inHull(const vector<P>& l, P p, bool strict = true) {
|
||||
int a = 1, b = sz(l) - 1, r = !strict;
|
||||
if (sz(l) < 3) return r && onSegment(l[0], l.back(), p);
|
||||
if (sideOf(l[0], l[a], l[b]) > 0) swap(a, b);
|
||||
if (sideOf(l[0], l[a], p) >= r || sideOf(l[0], l[b], p)<= -r)
|
||||
return false;
|
||||
while (abs(a - b) > 1) {
|
||||
int c = (a + b) / 2;
|
||||
(sideOf(l[0], l[c], p) > 0 ? b : a) = c;
|
||||
}
|
||||
return sgn(l[a].cross(l[b], p)) < r;
|
||||
}
|
||||
|
||||
// convex hull
|
||||
vector<pll> convex_hull(vector<pii> &arr){
|
||||
vector<pll> up, down;
|
||||
for(auto p : arr){
|
||||
while(up.size() >= 2 && ccw(up[up.size() - 2], up[up.size() - 1], p) >= 0) up.pop_back();
|
||||
while(down.size() >= 2 && ccw(down[down.size() - 2], down[down.size() - 1], p) <= 0) down.pop_back();
|
||||
up.push_back(p);
|
||||
down.push_back(p);
|
||||
}
|
||||
up.insert(up.end(), down.rbegin() + 1, down.rend());
|
||||
return up;
|
||||
}
|
||||
|
||||
// rotating callipers
|
||||
typedef Point<ll> P;
|
||||
array<P, 2> hullDiameter(vector<P> S) {
|
||||
int n = sz(S), j = n < 2 ? 0 : 1;
|
||||
pair<ll, array<P, 2>> res({0, {S[0], S[0]}});
|
||||
rep(i,0,j)
|
||||
for (;; j = (j + 1) % n) {
|
||||
res = max(res, {(S[i] - S[j]).dist2(), {S[i], S[j]}});
|
||||
if ((S[(j + 1) % n] - S[j]).cross(S[i + 1] - S[i]) >= 0)
|
||||
break;
|
||||
}
|
||||
return res.second;
|
||||
}
|
||||
|
||||
// Closest pair
|
||||
typedef Point<ll> P;
|
||||
pair<P, P> closest(vector<P> v) {
|
||||
assert(sz(v) > 1);
|
||||
set<P> S;
|
||||
sort(all(v), [](P a, P b) { return a.y < b.y; });
|
||||
pair<ll, pair<P, P>> ret{LLONG_MAX, {P(), P()}};
|
||||
int j = 0;
|
||||
for (P p : v) {
|
||||
P d{1 + (ll)sqrt(ret.first), 0};
|
||||
while (v[j].y <= p.y - d.x) S.erase(v[j++]);
|
||||
auto lo = S.lower_bound(p - d), hi = S.upper_bound(p + d);
|
||||
for (; lo != hi; ++lo)
|
||||
ret = min(ret, {(*lo - p).dist2(), {*lo, p}});
|
||||
S.insert(p);
|
||||
}
|
||||
return ret.second;
|
||||
}
|
||||
109
2025spring/source/Geometry/namespace_geometry.cpp
Normal file
109
2025spring/source/Geometry/namespace_geometry.cpp
Normal file
@@ -0,0 +1,109 @@
|
||||
template <typename T>
|
||||
class Point {
|
||||
public:
|
||||
T x, y;
|
||||
Point() : x(0), y(0) {};
|
||||
Point(T _x, T _y) : x(_x), y(_y) {};
|
||||
|
||||
Point operator+(Point p2){
|
||||
return Point(x + p2.x, y + p2.y);
|
||||
}
|
||||
Point operator-(Point p2){
|
||||
return Point(x - p2.x, y - p2.y);
|
||||
}
|
||||
T operator*(Point p2){
|
||||
return x * p2.x + y * p2.y;
|
||||
}
|
||||
T operator/(Point p2) {
|
||||
return x * p2.y - p2.x * y;
|
||||
}
|
||||
T operator==(Point p2) {
|
||||
return (x == p2.x) && (y == p2.y);
|
||||
}
|
||||
T sqdist() {
|
||||
return x*x + y*y;
|
||||
}
|
||||
bool operator<(Point p2) {
|
||||
if(y == p2.y)
|
||||
return x < p2.x;
|
||||
return y < p2.y;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
namespace geometry {
|
||||
template <typename T>
|
||||
ll ccw(Point<T> center, Point<T> p2, Point<T> p3) {
|
||||
ll res = (p2 - center) / (p3 - center);
|
||||
return (res > 0) - (res < 0);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
double theta(Point<T> center, Point<T> p2, Point<T> p3) {
|
||||
return acos(p2 * p3 / sqrt(p2.sqdist() * p3.sqdist()));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
function<bool(Point<T> &, Point<T> &, Point<T>)> cmp_point = [](Point<T> &l, Point<T> &r, Point<T> O = {(T)0, (T)0}) -> bool {
|
||||
return (l < O) != (r < O) ? l < r : l/r > 0;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
T sq_dist(Point<T> &p1, Point<T> &p2) {
|
||||
return (p2.x - p1.x)*(p2.x - p1.x) + (p2.y - p1.y)*(p2.y - p1.y);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
double dist(Point<T> &p1, Point<T> &p2) {
|
||||
return sqrt((double)sq_dist(p1, p2));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
double line_point_dist(pair<Point<T>, Point<T>> &l, Point<T> p)
|
||||
{
|
||||
Point<T> p1 = p - l.first, p2 = l.second - l.first;
|
||||
return abs(p1 / p2)/(dist(l.first, l.second));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
double line_min_dist(pair<Point<T>, Point<T>> &l1, pair<Point<T>, Point<T>> &l2) {
|
||||
double ans = INFINITY;
|
||||
ans = min({ans, dist(l1.first, l2.first), dist(l1.first, l2.second), dist(l1.second, l2.first), dist(l1.second, l2.second)});
|
||||
|
||||
if((l1.second - l1.first)*(l2.first - l1.first) > 0 && (l1.first - l1.second)*(l2.first - l1.second) > 0)
|
||||
ans = min({ans, line_point_dist<double>(l1, l2.first)});
|
||||
if((l1.second - l1.first)*(l2.second - l1.first) > 0 && (l1.first - l1.second)*(l2.second - l1.second) > 0)
|
||||
ans = min({ans, line_point_dist<double>(l1, l2.second)});
|
||||
swap(l1, l2);
|
||||
if((l1.second - l1.first)*(l2.first - l1.first) > 0 && (l1.first - l1.second)*(l2.first - l1.second) > 0)
|
||||
ans = min({ans, line_point_dist<double>(l1, l2.first)});
|
||||
if((l1.second - l1.first)*(l2.second - l1.first) > 0 && (l1.first - l1.second)*(l2.second - l1.second) > 0)
|
||||
ans = min({ans, line_point_dist<double>(l1, l2.second)});
|
||||
swap(l1, l2);
|
||||
return ans;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
vector<T> convex_hull(vector<Point<T>> &pts) {
|
||||
assert(pts.size() >= 2);
|
||||
vector<Point<T>> res;
|
||||
|
||||
swap(pts[0], *min_element(pts.begin(), pts.end()));
|
||||
sort(pts.begin()+1, pts.end(), [&pts](Point<T> &a, Point<T> &b){
|
||||
ll cw = ccw(pts[0], a, b);
|
||||
if(cw) return cw > 0;
|
||||
return sq_dist(pts[0], a) < sq_dist(pts[0], b);
|
||||
});
|
||||
auto itr = pts.begin();
|
||||
res.push_back(*(itr++)); res.push_back(*(itr++));
|
||||
|
||||
while(itr != pts.end())
|
||||
{
|
||||
while(res.size() >= 2 && ccw(res[res.size()-2], res[res.size()-1], *itr) <= 0)
|
||||
res.pop_back();
|
||||
res.push_back(*(itr++));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
using namespace geometry;
|
||||
13
2025spring/source/Graph/BipartiteMatching.cpp
Normal file
13
2025spring/source/Graph/BipartiteMatching.cpp
Normal file
@@ -0,0 +1,13 @@
|
||||
vector<int> sideadj[N];
|
||||
int selby[M];
|
||||
int chk[M], c;
|
||||
bool matching(int s) {
|
||||
for(auto i : sideadj[s]) {
|
||||
if(chk[i] == c) continue;
|
||||
chk[i] = c;
|
||||
if(selby[i] and !matching(selby[i])) continue;
|
||||
selby[i] = s;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
69
2025spring/source/Graph/Dinic.cpp
Normal file
69
2025spring/source/Graph/Dinic.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
struct Edge {
|
||||
int to, cap, now;
|
||||
Edge* rev;
|
||||
Edge(int to,int cap):to(to), cap(cap), now(0){}
|
||||
int left(){return cap - now;}
|
||||
void flow(int f){now += f; rev->now -= f;}
|
||||
void reset(){now = 0;}
|
||||
};
|
||||
vector<Edge*> adj[N];
|
||||
|
||||
int lv[N]; bool chk[N];
|
||||
bool bfs(int S, int T) {
|
||||
queue<int> q;
|
||||
q.push(S); lv[S] = 0; chk[S] = true;
|
||||
while(!q.empty()) {
|
||||
int s = q.front(); q.pop();
|
||||
for(auto i : adj[s]) {
|
||||
if(i->left() and !chk[i->to]) {
|
||||
lv[i->to] = lv[s]+1; chk[i->to] = true;
|
||||
q.push(i->to);
|
||||
}
|
||||
}
|
||||
}
|
||||
return chk[T];
|
||||
}
|
||||
|
||||
Edge* hist[N]; int last[N];
|
||||
bool dfs(int s, int T) {
|
||||
if(s == T) return true;
|
||||
|
||||
for(int &j=last[s]; j < adj[s].size(); j++) {
|
||||
int i = adj[s][j]->to;
|
||||
if(adj[s][j]->left() == 0 or lv[i] != lv[s]+1) continue;
|
||||
hist[i] = adj[s][j];
|
||||
|
||||
if(dfs(i, T)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ll flow(int S,int T) {
|
||||
ll ans = 0;
|
||||
while(bfs(S, T)) {
|
||||
while(dfs(S, T)) {
|
||||
int m = 2e9;
|
||||
int now = T;
|
||||
while(S != now) {
|
||||
m = min(m, hist[now]->left());
|
||||
now = hist[now]->rev->to;
|
||||
}
|
||||
now = T;
|
||||
while(S != now)
|
||||
hist[now]->flow(m), now = hist[now]->rev->to;
|
||||
ans += m;
|
||||
}
|
||||
memset(last, 0, sizeof last);
|
||||
memset(chk, 0, sizeof chk);
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
// isDir : isDirected => 양방향 간선이면 false
|
||||
void connect(int from, int to, int cap, bool isDir = true) {
|
||||
Edge *fw, *bw;
|
||||
fw = new Edge(to, cap);
|
||||
bw = new Edge(from, !isDir ? cap : 0);
|
||||
fw->rev = bw; bw->rev = fw;
|
||||
adj[from].push_back(fw);
|
||||
adj[to].push_back(bw);
|
||||
}
|
||||
67
2025spring/source/Graph/MCMF.cpp
Normal file
67
2025spring/source/Graph/MCMF.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
struct Edge {
|
||||
int to, cap, now;
|
||||
ll cost;
|
||||
Edge* rev;
|
||||
Edge(int to,int cap, ll cost)
|
||||
:to(to), cap(cap), now(0), cost(cost){}
|
||||
int left(){return cap - now;}
|
||||
ll flow(int f)
|
||||
{now += f; rev->now -= f; return cost * f;}
|
||||
void reset(){now = 0;}
|
||||
};
|
||||
vector<Edge*> adj[N];
|
||||
Edge* hist[N]; ll dist[N]; bool inQueue[N], chk[N];
|
||||
bool spfa(int s, int t) {
|
||||
memset(dist, 0, sizeof(dist));
|
||||
memset(chk, 0, sizeof(chk)); chk[s] = true;
|
||||
queue<int> q;
|
||||
memset(inQueue, 0, sizeof(inQueue));
|
||||
q.push(s); inQueue[s] = true;
|
||||
while(!q.empty()) {
|
||||
int now = q.front();
|
||||
q.pop(); inQueue[now] = false;
|
||||
|
||||
for(auto e : adj[now]) {
|
||||
int next = e->to;
|
||||
if(e->left() > 0 and
|
||||
(chk[next] == false
|
||||
or dist[next] > dist[now] + e->cost)) {
|
||||
chk[next] = true;
|
||||
dist[next] = dist[now] + e->cost;
|
||||
hist[next] = e;
|
||||
if(!inQueue[next])
|
||||
q.push(next), inQueue[next] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return chk[t];
|
||||
}
|
||||
// cost가 들어가면 항상 단방향만 가능하다. (양방향 : 2번 connect)
|
||||
void connect(int from, int to, int cap, ll cost) {
|
||||
Edge *fw, *bw;
|
||||
fw = new Edge(to, cap, cost);
|
||||
bw = new Edge(from, 0, -cost);
|
||||
fw->rev = bw; bw->rev = fw;
|
||||
adj[from].push_back(fw);
|
||||
adj[to].push_back(bw);
|
||||
}
|
||||
//maximum matching & minimum cost
|
||||
pair<ll, ll> flow(int S,int T) {
|
||||
ll ans = 0; ll cost = 0;
|
||||
while(spfa(S, T)) {
|
||||
int m = 2e9;
|
||||
|
||||
int now = T;
|
||||
while(S != now) {
|
||||
m = min(m, hist[now]->left());
|
||||
now = hist[now]->rev->to;
|
||||
}
|
||||
now = T;
|
||||
while(S != now) {
|
||||
cost += hist[now]->flow(m);
|
||||
now = hist[now]->rev->to;
|
||||
}
|
||||
ans += m;
|
||||
}
|
||||
return {ans, cost};
|
||||
}
|
||||
28
2025spring/source/Graph/TarjanSCC.cpp
Normal file
28
2025spring/source/Graph/TarjanSCC.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
vi adj[N];
|
||||
int in[N], c = 0;
|
||||
stack<int> p;
|
||||
bool fin[N]; int scn[N], nscc = 0;
|
||||
int dfs(int s) {
|
||||
in[s] = ++c;
|
||||
p.push(s);
|
||||
|
||||
int m = c;
|
||||
for(auto i : adj[s]) {
|
||||
if(in[i] == 0) m = min(m, dfs(i));
|
||||
else if(!fin[i]) m = min(m, in[i]);
|
||||
}
|
||||
|
||||
if(m == in[s]) {
|
||||
nscc++;
|
||||
while(p.top() != s)
|
||||
{
|
||||
int i = p.top(); p.pop();
|
||||
scn[i] = nscc; fin[i] = true;
|
||||
}
|
||||
p.pop();
|
||||
scn[s] = nscc; fin[s] = true;
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
forr(i, n) if(!fin[i]) dfs(i);
|
||||
81
2025spring/source/Linear Algebra/Matrix.cpp
Normal file
81
2025spring/source/Linear Algebra/Matrix.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
class Matrix {
|
||||
private:
|
||||
// c: col 개수, r: row 개수
|
||||
ll c, r, mod;
|
||||
vector<vector<ll>> arr;
|
||||
ll power(ll x, ll y, ll p) {
|
||||
if (y == 0) return 1;
|
||||
ll v = power(x, y/2, p) % p;
|
||||
v = (v * v) % p;
|
||||
return (y%2 == 0)? v : (x * v) % p;
|
||||
}
|
||||
ll modInverse(ll a, ll p) { return power(a, p-2, p); }
|
||||
|
||||
public:
|
||||
Matrix(int _n, int _m, ll p) : c(_n), r(_m), mod(p) {
|
||||
arr.resize(c, vector<ll>(r, 0));
|
||||
}
|
||||
|
||||
void setI() {
|
||||
assert(c == r);
|
||||
for(int i=0; i<c; i++) arr[i][i] = 1;
|
||||
}
|
||||
|
||||
ll *operator[](ll i) { return &arr[i][0]; }
|
||||
|
||||
void swaprow(ll i, ll j) {
|
||||
if (i == j) return;
|
||||
for (int k = 0; k < c; k++)
|
||||
swap(arr[i][k], arr[j][k]);
|
||||
}
|
||||
|
||||
pair<bool, Matrix> Inverse() {
|
||||
assert(c == r);
|
||||
Matrix victim = *this;
|
||||
Matrix retm(c, c, mod);
|
||||
retm.setI();
|
||||
|
||||
for (int k = 0; k < c; k++) {
|
||||
int t = k - 1;
|
||||
while (t + 1 < c && !victim[++t][k]);
|
||||
if (t == c - 1 && !victim[t][k])
|
||||
return {false, Matrix(0, 0, 0)};
|
||||
victim.swaprow(k, t), retm.swaprow(k, t);
|
||||
ll d = victim[k][k];
|
||||
|
||||
for (int j = 0; j < c; j++) {
|
||||
victim[k][j] = (victim[k][j] * modInverse(d, mod))%mod;
|
||||
retm[k][j] = (retm[k][j] * modInverse(d, mod))%mod;
|
||||
}
|
||||
|
||||
for (int i = 0; i<c; i++)
|
||||
if (i != k) {
|
||||
ll m = victim[i][k];
|
||||
for (int j = 0; j < c; j++) {
|
||||
if (j >= k) victim[i][j] = (victim[i][j] - victim[k][j] * m + mod*mod)%mod;
|
||||
retm[i][j] = (retm[i][j] - retm[k][j] * m + mod*mod)%mod;
|
||||
}
|
||||
}
|
||||
}
|
||||
return {true, retm};
|
||||
}
|
||||
|
||||
vector<double> GaussElimination() {
|
||||
assert(c == r - 1);
|
||||
vector<double> retv(c, 0.0);
|
||||
|
||||
for(ll i=0; i<c; i++) for(ll j=1+i; j<c; j++) {
|
||||
double tmp = arr[j][i];
|
||||
for(ll k=i; k<r; k++)
|
||||
arr[j][k] = arr[j][k] - (tmp / arr[i][i]) * arr[i][k];
|
||||
}
|
||||
|
||||
ll p = c, q = 0;
|
||||
for (ll p = c - 1; p >= 0; p--) {
|
||||
retv[p] = arr[p][c] / arr[p][p];
|
||||
for (q = p - 1; q >= 0; q--)
|
||||
arr[q][c] = arr[q][c] - arr[q][p] * retv[p];
|
||||
}
|
||||
return retv;
|
||||
}
|
||||
};
|
||||
13
2025spring/source/Math/CRT.cpp
Normal file
13
2025spring/source/Math/CRT.cpp
Normal file
@@ -0,0 +1,13 @@
|
||||
pll crt(pll p, pll q) {
|
||||
if(p.fi > q.fi) swap(p, q);
|
||||
auto [a, A] = p;
|
||||
auto [b, B] = q;
|
||||
|
||||
ll g = gcd(A, B);
|
||||
if((b-a)%g != 0) return {-1, -1};
|
||||
|
||||
ll i = A, j = B, k = b-a;
|
||||
i/=g; j/=g; k/=g;
|
||||
auto [x, y] = diophantos(i, j);
|
||||
return {(ll)((a+(lll)A*k*x)%(A*B/g)), A*B/g};
|
||||
}
|
||||
12
2025spring/source/Math/Diophantos.cpp
Normal file
12
2025spring/source/Math/Diophantos.cpp
Normal file
@@ -0,0 +1,12 @@
|
||||
pll diophantos(ll a, ll b) {
|
||||
assert(a>0 and b>=0);
|
||||
if(b == 0) return {1, 0};
|
||||
auto [y, x] = diophantos(b, a%b); y = y-(a/b)*x;
|
||||
if(x < 0 or x >= b) {
|
||||
ll t = x/b;
|
||||
if(x%b < 0) t--;
|
||||
|
||||
x -= b*t; y += a*t;
|
||||
}
|
||||
return {x, y};
|
||||
}
|
||||
74
2025spring/source/Math/FFTConv.cpp
Normal file
74
2025spring/source/Math/FFTConv.cpp
Normal file
@@ -0,0 +1,74 @@
|
||||
using cpx = complex<double>;
|
||||
using vcpx = vector<cpx>;
|
||||
void fft(vcpx &a, bool inv = false) {
|
||||
int n = a.size(), j = 0; assert((n&-n) == n);
|
||||
for(int i=1; i<n; i++) {
|
||||
int bit = (n >> 1);
|
||||
while(j >= bit) {
|
||||
j -= bit;
|
||||
bit >>= 1;
|
||||
}
|
||||
j += bit;
|
||||
if(i < j) swap(a[i], a[j]);
|
||||
}
|
||||
|
||||
vcpx roots(n/2);
|
||||
prec c = 2 * pi * (inv ? -1 : 1);
|
||||
for(int i=0; i<n/2; i++)
|
||||
roots[i] = cpx(cosl(c * i / n), sinl(c * i / n));
|
||||
|
||||
for(int i=2; i<=n; i<<=1) {
|
||||
int step = n / i;
|
||||
for(int j=0; j<n; j+=i) {
|
||||
for(int k=0; k<i/2; k++) {
|
||||
cpx u = a[j+k], v = a[j+k+i/2]*roots[step*k];
|
||||
a[j+k] = u+v;
|
||||
a[j+k+i/2] = u-v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(inv) for(int i=0; i<n; i++) a[i] /= n;
|
||||
}
|
||||
|
||||
ll mod = 1e9+7;
|
||||
vl conv(const vl& AA,const vl& BB) {
|
||||
const ll G = 1<<15;
|
||||
int n = AA.size()+BB.size()-1;
|
||||
int m = 1; while(m < n) m<<=1;
|
||||
|
||||
int a = AA.size(), b = BB.size();
|
||||
|
||||
vcpx A(m), B(m), C(m), D(m);
|
||||
fors(i, 0, a-1) A[i] = cpx(AA[i]/G, AA[i]%G);
|
||||
fors(i, 0, b-1) B[i] = cpx(BB[i]/G, BB[i]%G);
|
||||
|
||||
fft(A); fft(B);
|
||||
|
||||
fors(i, 0, m-1) {
|
||||
int j = i?m-i:0;
|
||||
cpx A1 = (A[i]+conj(A[j]))*cpx(0.5, 0);
|
||||
cpx A2 = (A[i]-conj(A[j]))*cpx(0, -0.5);
|
||||
|
||||
cpx B1 = (B[i]+conj(B[j]))*cpx(0.5, 0);
|
||||
cpx B2 = (B[i]-conj(B[j]))*cpx(0, -0.5);
|
||||
|
||||
C[i] = A1*B1 + A2*B2*cpx(0, 1);
|
||||
D[i] = A2*B1 + A1*B2*cpx(0, 1);
|
||||
}
|
||||
|
||||
fft(C, true); fft(D, true);
|
||||
|
||||
|
||||
vl ret(m); ll G1 = G%mod, G2 = (lll)G*G%mod;
|
||||
fors(i, 0, m-1) {
|
||||
ll p = ll(C[i].real()+0.5);
|
||||
ll q = ll(D[i].real()+0.5) + ll(D[i].imag()+0.5);
|
||||
ll r = ll(C[i].imag()+0.5);
|
||||
|
||||
p %= mod; q %= mod; r %= mod;
|
||||
ret[i] = (((lll)p*G2)%mod+((lll)q*G1)%mod+r%mod)%mod;
|
||||
}
|
||||
ret.resize(n);
|
||||
return ret;
|
||||
}
|
||||
7
2025spring/source/Math/FloorSum.cpp
Normal file
7
2025spring/source/Math/FloorSum.cpp
Normal file
@@ -0,0 +1,7 @@
|
||||
ll floor_sum(ll a, ll b, ll c, ll n)
|
||||
{
|
||||
if(a == 0) return b/c*n;
|
||||
if(a>=c or b>=c) return n*(n-1)/2 * (a/c) + n * (b/c) + floor_sum(a%c, b%c, c, n);
|
||||
ll m = (a*(n-1)+b)/c;
|
||||
return m*n - floor_sum(c, c-b+a-1, a, m);
|
||||
}
|
||||
12
2025spring/source/Math/Harmonic.cpp
Normal file
12
2025spring/source/Math/Harmonic.cpp
Normal file
@@ -0,0 +1,12 @@
|
||||
ll harmonic(ll n) {
|
||||
ll ans = 0;
|
||||
for(ll i = 1; i <= n; i = n/(n/i)+ 1) {
|
||||
//for j \in [i, n/(n/i)] : n/j == n/i
|
||||
|
||||
ans += n/i * (n/(n/i) - i + 1);
|
||||
|
||||
// \sum_{i=1}^n {f(n/i)}
|
||||
// ans += f(n/i) * (n/(n/i) - i + 1)
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
26
2025spring/source/Math/MillerRabin.cpp
Normal file
26
2025spring/source/Math/MillerRabin.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
ll pow(ll a, ll b, ll mod) {
|
||||
ll ret = 1;
|
||||
for(int st=0; (1LL<<st) <= b; st++) {
|
||||
if((1LL<<st) & b) ret=(lll)ret*a%mod;
|
||||
a=(lll)a*a%mod;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
bool miller(ll n, ll a) {
|
||||
if(n == a) return true;
|
||||
ll x = n-1;
|
||||
if(pow(a, x, n) != 1) return false;
|
||||
while(x%2==0) {
|
||||
x/=2;
|
||||
ll t = pow(a, x, n);
|
||||
if(t!=1 and t!=n-1) return false;
|
||||
if(t==n-1) return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool is_p(ll n) {
|
||||
if(n<=2) return n==2;
|
||||
vi D = {2, 3, 5, 7, 11, 13, 17, 23, 29, 31, 37};
|
||||
for(auto i:D) if(!miller(n, i)) return false;
|
||||
return true;
|
||||
}
|
||||
82
2025spring/source/Math/NTT.cpp
Normal file
82
2025spring/source/Math/NTT.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
namespace GMS {
|
||||
template<ll mod>
|
||||
ll pow(ll a, ll b) {
|
||||
static_assert(mod <= (ll)2e9, "mod should be less than 2e9");
|
||||
a %= mod;
|
||||
ll ret = 1;
|
||||
while(b != 0) {
|
||||
if(b&1) ret = ret*a%mod;
|
||||
a = a*a%mod; b>>=1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
template<ll mod, ll w>
|
||||
void ntt(vector<ll> &a, bool inv = false) {
|
||||
static_assert(mod <= (ll)2e9, "mod should be less than 2e9");
|
||||
int n = a.size(), j = 0;
|
||||
|
||||
assert((n & -n) == n && (mod-1)%n == 0);
|
||||
|
||||
for(int i=1; i<n; i++) {
|
||||
int bit = (n >> 1);
|
||||
while(j >= bit) {
|
||||
j -= bit;
|
||||
bit >>= 1;
|
||||
}
|
||||
j += bit;
|
||||
if(i < j) swap(a[i], a[j]);
|
||||
}
|
||||
|
||||
static vector<ll> root[30], iroot[30];
|
||||
for(int st=1; (1<<st) <= n; st++) {
|
||||
if(root[st].empty()) {
|
||||
ll t = pow<mod>(w, (mod-1)/(1<<st));
|
||||
|
||||
root[st].pb(1);
|
||||
for(int i=1; i<(1<<(st-1)); i++)
|
||||
root[st].pb(root[st].back()*t%mod);
|
||||
}
|
||||
if(iroot[st].empty()) {
|
||||
ll t = pow<mod>(w, (mod-1)/(1<<st));
|
||||
t = pow<mod>(t, mod-2);
|
||||
|
||||
iroot[st].pb(1);
|
||||
for(int i=1; i<(1<<(st-1)); i++)
|
||||
iroot[st].pb(iroot[st].back()*t%mod);
|
||||
}
|
||||
}
|
||||
|
||||
vector<ll>* r = (inv?root:iroot);
|
||||
|
||||
for(int st = 1; (1<<st) <= n; st++) {
|
||||
int i = 1<<st; //int step = n / i;
|
||||
for(int j=0; j<n; j+=i) {
|
||||
for(int k=0; k<i/2; k++) {
|
||||
ll u = a[j+k], v = a[j+k+i/2] * r[st][k]%mod;
|
||||
a[j+k] = (u+v)%mod;
|
||||
a[j+k+i/2] = (mod+u-v)%mod;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(inv) {
|
||||
ll in = pow<mod>(n, mod-2);
|
||||
for(int i=0; i<n; i++) a[i] = a[i]*in%mod;
|
||||
}
|
||||
}
|
||||
|
||||
template<ll mod, ll w>
|
||||
vl conv(vl A, vl B) {
|
||||
int n = A.size(), m = B.size();
|
||||
int t = 1; while(t < n+m-1) t*=2;
|
||||
A.resize(t); B.resize(t);
|
||||
|
||||
ntt<mod, w>(A); ntt<mod, w>(B);
|
||||
|
||||
fors(i, 0, t-1) A[i] = A[i]*B[i]%mod;
|
||||
|
||||
ntt<mod, w>(A, true);
|
||||
A.resize(n+m-1);
|
||||
|
||||
return A;
|
||||
}
|
||||
} // namespace GMS
|
||||
22
2025spring/source/Math/PolladRho.cpp
Normal file
22
2025spring/source/Math/PolladRho.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
void fact(ll n, vl& ret) {
|
||||
if(n == 1) return;
|
||||
else if(n%2 == 0) ret.pb(2), fact(n/2, ret);
|
||||
else if(is_p(n)) ret.pb(n);
|
||||
else {
|
||||
ll a, b, c, g = n;
|
||||
auto f = [&c, &n](ll x)->ll{return (c+(lll)x*x)%n;};
|
||||
|
||||
do {
|
||||
if(g == n) a=b=rand()%(n-2)+2, c=rand()%20+1;
|
||||
a=f(a); b=f(f(b));
|
||||
g = gcd(a-b, n);
|
||||
} while(g == 1);
|
||||
fact(g, ret); fact(n/g, ret);
|
||||
}
|
||||
}
|
||||
vl po_rho(ll n) {
|
||||
vl ret;
|
||||
fact(n, ret);
|
||||
sort(all(ret));
|
||||
return ret;
|
||||
}
|
||||
180
2025spring/source/Math/Polynomial.cpp
Normal file
180
2025spring/source/Math/Polynomial.cpp
Normal file
@@ -0,0 +1,180 @@
|
||||
namespace GMS {
|
||||
template<ll mod, ll w>
|
||||
struct Qring : public vl {
|
||||
using poly = Qring<mod, w>;
|
||||
Qring() : vl(1, 0) {}
|
||||
Qring(ll c) : vl(1, c%mod) {}
|
||||
Qring(ll c, int n) : vl(n, c%mod) {}
|
||||
Qring(const vl& cp) : vl(cp) {for(auto &i:*this) i%=mod;}
|
||||
|
||||
ll& operator[](ll idx) {
|
||||
if((unsigned)idx < size()) return vl::operator[](idx);
|
||||
this->resize(idx+1); return vl::operator[](idx);
|
||||
}
|
||||
ll operator[](ll idx) const {
|
||||
if((unsigned)idx < size()) return vl::operator[](idx);
|
||||
return 0LL;
|
||||
}
|
||||
|
||||
void adjust() {
|
||||
while(size() > 1 and back() == 0) pop_back();
|
||||
}
|
||||
void adjust(int n){resize(n, 0);}
|
||||
|
||||
ll operator()(ll x) {
|
||||
x %= mod; ll ret = 0;
|
||||
for(auto it=rbegin(); it!=rend(); it++)
|
||||
ret = (ret*x+*it)%mod;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
friend poly operator%(const poly& A, int B){ // remainder by x^B
|
||||
poly ret(A); ret.resize(B, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
friend poly operator+(const poly& A, const poly& B) {
|
||||
int n = max(A.size(), B.size()); poly ret(0, n);
|
||||
fors(i, 0, n-1) ret[i] = A[i]+B[i];
|
||||
for(auto&i:ret) if(i >= mod) i -= mod;
|
||||
return ret.adjust(), ret;
|
||||
}
|
||||
|
||||
friend poly operator-(const poly& A) {
|
||||
int n = A.size(); poly ret(0, n);
|
||||
fors(i, 0, n-1) ret[i] = A[i]?mod-A[i]:0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
friend poly operator-(const poly& A, const poly& B) {
|
||||
int n = max(A.size(), B.size());
|
||||
poly ret(0, n);
|
||||
fors(i, 0, n-1) ret[i] = (mod+A[i]-B[i])%mod;
|
||||
ret.adjust();
|
||||
return ret;
|
||||
}
|
||||
|
||||
friend poly operator*(ll x, const poly& B) {
|
||||
poly ret(B); x %= mod;
|
||||
for(auto &i : ret) i = (i*x)%mod;
|
||||
ret.adjust();
|
||||
return ret;
|
||||
}
|
||||
|
||||
friend poly operator*(const poly& A, const poly& B) {
|
||||
poly ret = conv<mod, w>(A, B);
|
||||
// ACL : poly ret = atcoder::convolution<mod>(A, B);
|
||||
ret.adjust();
|
||||
return ret;
|
||||
}
|
||||
|
||||
friend poly inv(const poly& A, int t) { assert(A[0] != 0);
|
||||
poly g = pow<mod>(A[0], mod-2);
|
||||
|
||||
int st=1;
|
||||
while(st < t){st*=2; g = (-A%st*g%st+2)*g%st;}
|
||||
|
||||
g.adjust(t);
|
||||
return g;
|
||||
}
|
||||
|
||||
friend poly diff(const poly& A) {
|
||||
int n = A.size(); poly ret(0, n-1);
|
||||
fors(i, 0, n-2) ret[i] = (i+1)*A[i+1]%mod;
|
||||
return ret;
|
||||
}
|
||||
friend poly inte(const poly& A) {
|
||||
static vector<ll> inv(1, 1);
|
||||
int n = A.size(); poly ret(0, n+1);
|
||||
inv.resize(max((int)inv.size(), n+1));
|
||||
|
||||
fors(i, 1, n) if(inv[i] == 0) inv[i] = pow<mod>(i, mod-2);
|
||||
fors(i, 1, n) ret[i] = inv[i]*A[i-1]%mod;
|
||||
return ret;
|
||||
}
|
||||
|
||||
friend poly log(const poly& A, int t) { assert(A[0] == 1);
|
||||
return inte(diff(A) * inv(A, t)%t)%t;
|
||||
}
|
||||
|
||||
friend poly exp(const poly& A, int t) { assert(A[0] == 0);
|
||||
poly g = 1; int st = 1;
|
||||
while(st < t) {st*=2; g = (A%st-log(g, st)+1)*g%st;}
|
||||
return g.adjust(), g;
|
||||
}
|
||||
|
||||
friend poly pow(const poly& A, ll b, ll t) {
|
||||
poly ret(A); ret.adjust();
|
||||
if(ret.size() == 1) {
|
||||
ret[0] = pow<mod>(ret[0], b);
|
||||
ret.adjust(t);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ll idx = 0; while(ret[idx] == 0) idx++;
|
||||
if((__int128_t) idx * b >= t) return poly(0, t);
|
||||
|
||||
ll c = ret[idx]; ll ic = pow<mod>(ret[idx], mod-2); poly g;
|
||||
int n = ret.size();
|
||||
fors(i, idx, n-1) g[i-idx] = ret[i]*ic%mod;
|
||||
g.resize(t-idx*b);
|
||||
|
||||
g = exp(b * log(g, t-idx*b), t-idx*b);
|
||||
c = pow<mod>(c, b);
|
||||
|
||||
ret = poly(0, t); fors(i, idx*b, t-1) ret[i] = g[i-idx*b] * c % mod;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//Only just Polynomial, not Qring
|
||||
void rev() {
|
||||
int n=size(); poly& F = *this;
|
||||
for(int i=0; i<n/2; i++) std::swap(F[i], F[n-i-1]);
|
||||
}
|
||||
friend poly div_quot(poly F, poly G) {
|
||||
F.adjust(); G.adjust();
|
||||
ll df = F.size(), dg = G.size();
|
||||
if(df < dg) return poly(0);
|
||||
|
||||
F.rev(); G.rev();
|
||||
F = F%(df-dg+1)*inv(G, df-dg+1)%(df-dg+1); F.rev();
|
||||
return F;
|
||||
}
|
||||
friend poly div_rem(poly F, poly G) {return F-G*div_quot(F, G);}
|
||||
|
||||
friend poly shift(const poly& F, ll c) {
|
||||
ll n = F.size(); c %= mod;
|
||||
poly A(0, n); ll fac = 1;
|
||||
fors(i, 0, n-1) A[i] = F[i]*fac%mod, fac = fac*(i+1)%mod;
|
||||
A.rev();
|
||||
|
||||
poly C(1, n); fors(i, 1, n-1) C[i] = C[i-1]*c%mod;
|
||||
ll facc = fac = pow<mod>(fac, mod-2)*n%mod;
|
||||
fore(i, n-1, 0) C[i] = C[i]*fac%mod, fac = fac*i%mod;
|
||||
|
||||
poly B = C*A; B.resize(n); B.rev();
|
||||
fore(i, n-1, 0) B[i] = B[i]*facc%mod, facc = facc*i%mod;
|
||||
return B;
|
||||
}
|
||||
friend void calcG(vector<poly>& G, int i, int l, int r, const vl& p) {
|
||||
if(l == r){ll g = p[l]?mod-p[l]:0; G[i] = vl({g, 1}); return;}
|
||||
int mid = (l+r)/2;
|
||||
calcG(G, i*2, l, mid, p); calcG(G, i*2+1, mid+1, r, p);
|
||||
G[i] = G[i*2]*G[i*2+1];
|
||||
}
|
||||
friend void eval(const vector<poly>& G, int i, int l, int r, poly&& F, vl& ret) {
|
||||
if(l == r){ret[l] = F[0];return;}
|
||||
int mid=(l+r)/2;
|
||||
eval(G, i*2, l, mid, div_rem(F, G[i*2]), ret);
|
||||
eval(G, i*2+1, mid+1, r, div_rem(F, G[i*2+1]), ret);
|
||||
}
|
||||
friend vl multipoint_eval(const poly& A, const vl& B) {
|
||||
int m = B.size();
|
||||
vector<poly> G(4*m); calcG(G, 1, 0, m-1, B);
|
||||
vl ret(m, 0); eval(G, 1, 0, m-1, div_rem(A, G[1]), ret);
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
} // namespace GMS
|
||||
23
2025spring/source/Math/PrimitiveRoot.cpp
Normal file
23
2025spring/source/Math/PrimitiveRoot.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
ll primary_root(ll p) {
|
||||
std::random_device rd;
|
||||
std::mt19937 gen(rd());
|
||||
std::uniform_int_distribution<ll> distrib(1, p-1);
|
||||
|
||||
//distrib(gen);
|
||||
vl g = po_rho(p-1);
|
||||
|
||||
while(true) {
|
||||
ll c = distrib(gen);
|
||||
|
||||
bool ok = true; ll u = p-1;
|
||||
ll b = 1;
|
||||
for(auto i:g) {
|
||||
if(i != b) u = p-1;
|
||||
ll x = pow(c, u/i, p);
|
||||
if(x == 1) ok = false;
|
||||
u /= i; b = i;
|
||||
}
|
||||
|
||||
if(ok) return c;
|
||||
}
|
||||
}
|
||||
56
2025spring/source/Math/general_lucas.cpp
Normal file
56
2025spring/source/Math/general_lucas.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
vector<ll> euler(1000003, -1), primes;
|
||||
//Generate primes and also calculate the euler number
|
||||
void genprime() {
|
||||
for(ll i = 2;i<=1000002;i++) {
|
||||
if(euler[i]==-1) {
|
||||
primes.push_back(i);
|
||||
euler[i] = i-1;
|
||||
for(ll j = 2*i; j<=1000002; j+=i) {
|
||||
if(euler[j]==-1)euler[j] = j;
|
||||
euler[j] = (euler[j]/i)*(i-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//Calculates x raised to the power of p % m
|
||||
ll powll(ll x, ll p, ll m = 1ll<<62)
|
||||
// Mod inverse
|
||||
ll inverse(ll x, ll m)
|
||||
|
||||
//finds (n!)_p
|
||||
ll ff(ll n, ll p, ll q)
|
||||
{
|
||||
ll x = 1, y = powll(p, q);
|
||||
for(ll i = 2; i<=n;i++) if(i%p)
|
||||
x = (x*i)%y;
|
||||
return x%y;
|
||||
}
|
||||
|
||||
//Generalized Lucas Theorem calculates nCm mod p^q
|
||||
ll lucas_pow_comb(ll n, ll m, ll p, ll q) {
|
||||
ll r = n-m, x = powll(p, q);
|
||||
ll e0 = 0, eq = 0;
|
||||
ll mul = (p==2&&q>=3)? 1: -1;
|
||||
ll cr = r, cm = m, carry = 0, cnt = 0;
|
||||
while(cr||cm||carry) {
|
||||
cnt++;
|
||||
int rr = cr%p, rm = cm%p;
|
||||
if(rr + rm + carry >= p) {
|
||||
e0++;
|
||||
if(cnt>=q)eq++;
|
||||
}
|
||||
carry = (carry+rr+rm)/p;
|
||||
cr/=p; cm/=p;
|
||||
}
|
||||
mul = powll(p, e0)*powll(mul, eq);
|
||||
ll ret = (mul % x + x) % x;
|
||||
ll temp = 1;
|
||||
for(ll i = 0;;i++)//This is THE line that calculates the formula {
|
||||
ret = ((ret*ff((n/temp)%x, p, q)%x)%x*(inverse(ff((m/temp)%x, p, q), x)%x*inverse(ff((r/temp)%x, p, q), x)%x)%x)%x;
|
||||
|
||||
if(temp>n/p && temp>m/p && temp>r/p)
|
||||
break;
|
||||
temp = temp*p;
|
||||
}
|
||||
return (ret%x+x)%x;
|
||||
}
|
||||
152
2025spring/source/Math/math.tex
Normal file
152
2025spring/source/Math/math.tex
Normal file
@@ -0,0 +1,152 @@
|
||||
% Written by Anders Sjoqvist and Ulf Lundstrom, 2009
|
||||
% The main sources are: tinyKACTL, Beta and Wikipedia
|
||||
\subsection{Equations}
|
||||
\[ax^2+bx+c=0 \Rightarrow x = \frac{-b\pm\sqrt{b^2-4ac}}{2a}\]
|
||||
|
||||
The extremum is given by $x = -b/2a$.
|
||||
|
||||
\[\begin{aligned}ax+by=e\\cx+dy=f\end{aligned}
|
||||
\Rightarrow
|
||||
\begin{aligned}x=\dfrac{ed-bf}{ad-bc}\\y=\dfrac{af-ec}{ad-bc}\end{aligned}\]
|
||||
|
||||
In general, given an equation $Ax = b$, the solution to a variable $x_i$ is given by
|
||||
\[x_i = \frac{\det A_i'}{\det A} \]
|
||||
where $A_i'$ is $A$ with the $i$'th column replaced by $b$.
|
||||
|
||||
% \subsection{Recurrences}
|
||||
% If $a_n = c_1 a_{n-1} + \dots + c_k a_{n-k}$, and $r_1, \dots, r_k$ are distinct roots of $x^k - c_1 x^{k-1} - \dots - c_k$, there are $d_1, \dots, d_k$ s.t.
|
||||
% \[a_n = d_1r_1^n + \dots + d_kr_k^n. \]
|
||||
% Non-distinct roots $r$ become polynomial factors, e.g. $a_n = (d_1n + d_2)r^n$.
|
||||
|
||||
\subsection{Trigonometry}
|
||||
\begin{align*}
|
||||
\sin(v+w)&{}=\sin v\cos w+\cos v\sin w\\
|
||||
\cos(v+w)&{}=\cos v\cos w-\sin v\sin w\\
|
||||
\tan(v+w)&{}=\dfrac{\tan v+\tan w}{1-\tan v\tan w}\\
|
||||
\sin v+\sin w&{}=2\sin\dfrac{v+w}{2}\cos\dfrac{v-w}{2}\\
|
||||
\cos v+\cos w&{}=2\cos\dfrac{v+w}{2}\cos\dfrac{v-w}{2}\\
|
||||
(V+W)\tan(v-w)/2&{}=(V-W)\tan(v+w)/2
|
||||
\end{align*}
|
||||
where $V, W$ are lengths of sides opposite angles $v, w$.
|
||||
\begin{align*}
|
||||
a\cos x+b\sin x&=r\cos(x-\phi)\\
|
||||
a\sin x+b\cos x&=r\sin(x+\phi)
|
||||
\end{align*}
|
||||
where $r=\sqrt{a^2+b^2}, \phi=\operatorname{atan2}(b,a)$.
|
||||
|
||||
\subsection{Geometry}
|
||||
|
||||
\subsubsection{Triangles}
|
||||
Side lengths: $a,b,c$
|
||||
|
||||
Semiperimeter: $p=\dfrac{a+b+c}{2}$
|
||||
|
||||
Area: $A=\sqrt{p(p-a)(p-b)(p-c)}$
|
||||
|
||||
Circumradius: $R=\dfrac{abc}{4A}$
|
||||
|
||||
Inradius: $r=\dfrac{A}{p}$
|
||||
|
||||
Length of the median (divides the triangle into two equal area triangles): $m_a=\tfrac{1}{2}\sqrt{2b^2+2c^2-a^2}$
|
||||
|
||||
Length of the bisector (divides angles into two): $s_a=\sqrt{bc\left[1-\left(\dfrac{a}{b+c}\right)^2\right]}$
|
||||
|
||||
Law of sines: $\dfrac{\sin\alpha}{a}=\dfrac{\sin\beta}{b}=\dfrac{\sin\gamma}{c}=\dfrac{1}{2R}$
|
||||
|
||||
Law of cosines: $a^2=b^2+c^2-2bc\cos\alpha$
|
||||
|
||||
Law of tangents: $\dfrac{a+b}{a-b}=\dfrac{\tan\dfrac{\alpha+\beta}{2}}{\tan\dfrac{\alpha-\beta}{2}}$
|
||||
|
||||
|
||||
\subsubsection{Quadrilaterals}
|
||||
With side lengths $a,b,c,d$, diagonals $e, f$, diagonals angle $\theta$, area $A$ and
|
||||
magic flux $F=b^2+d^2-a^2-c^2$:
|
||||
|
||||
\[ 4A = 2ef \cdot \sin\theta = F\tan\theta = \sqrt{4e^2f^2-F^2} \]
|
||||
|
||||
For cyclic quadrilaterals the sum of opposite angles is $180^\circ$,
|
||||
$ef = ac + bd$, and $A = \sqrt{(p-a)(p-b)(p-c)(p-d)}$.
|
||||
|
||||
\subsubsection{Spherical coordinates}
|
||||
\begin{center}
|
||||
\includegraphics[width=25mm]{source/Math/sphericalCoordinates.pdf}
|
||||
\end{center}
|
||||
\[\begin{array}{cc}
|
||||
x = r\sin\theta\cos\phi & r = \sqrt{x^2+y^2+z^2}\\
|
||||
y = r\sin\theta\sin\phi & \theta = \textrm{acos}(z/\sqrt{x^2+y^2+z^2})\\
|
||||
z = r\cos\theta & \phi = \textrm{atan2}(y,x)
|
||||
\end{array}\]
|
||||
|
||||
\subsection{Derivatives/Integrals}
|
||||
\begin{align*}
|
||||
\dfrac{d}{dx}\arcsin x = \dfrac{1}{\sqrt{1-x^2}} &&& \dfrac{d}{dx}\arccos x = -\dfrac{1}{\sqrt{1-x^2}} \\
|
||||
\dfrac{d}{dx}\tan x = 1+\tan^2 x &&& \dfrac{d}{dx}\arctan x = \dfrac{1}{1+x^2} \\
|
||||
\int\tan ax = -\dfrac{\ln|\cos ax|}{a} &&& \int x\sin ax = \dfrac{\sin ax-ax \cos ax}{a^2} \\
|
||||
\int e^{-x^2} = \frac{\sqrt \pi}{2} \text{erf}(x) &&& \int xe^{ax}dx = \frac{e^{ax}}{a^2}(ax-1)
|
||||
\end{align*}
|
||||
|
||||
Integration by parts:
|
||||
\[\int_a^bf(x)g(x)dx = [F(x)g(x)]_a^b-\int_a^bF(x)g'(x)dx\]
|
||||
|
||||
\subsection{Sums}
|
||||
\[ c^a + c^{a+1} + \dots + c^{b} = \frac{c^{b+1} - c^a}{c-1}, c \neq 1 \]
|
||||
\begin{align*}
|
||||
1 + 2 + 3 + \dots + n &= \frac{n(n+1)}{2} \\
|
||||
1^2 + 2^2 + 3^2 + \dots + n^2 &= \frac{n(2n+1)(n+1)}{6} \\
|
||||
1^3 + 2^3 + 3^3 + \dots + n^3 &= \frac{n^2(n+1)^2}{4} \\
|
||||
1^4 + 2^4 + 3^4 + \dots + n^4 &= \frac{n(n+1)(2n+1)(3n^2 + 3n - 1)}{30} \\
|
||||
\end{align*}
|
||||
|
||||
\subsection{Series}
|
||||
$$e^x = 1+x+\frac{x^2}{2!}+\frac{x^3}{3!}+\dots,\,(-\infty<x<\infty)$$
|
||||
$$\ln(1+x) = x-\frac{x^2}{2}+\frac{x^3}{3}-\frac{x^4}{4}+\dots,\,(-1<x\leq1)$$
|
||||
$$\sqrt{1+x} = 1+\frac{x}{2}-\frac{x^2}{8}+\frac{2x^3}{32}-\frac{5x^4}{128}+\dots,\,(-1\leq x\leq1)$$
|
||||
$$\sin x = x-\frac{x^3}{3!}+\frac{x^5}{5!}-\frac{x^7}{7!}+\dots,\,(-\infty<x<\infty)$$
|
||||
$$\cos x = 1-\frac{x^2}{2!}+\frac{x^4}{4!}-\frac{x^6}{6!}+\dots,\,(-\infty<x<\infty)$$
|
||||
|
||||
\subsection{Probability theory}
|
||||
Let $X$ be a discrete random variable with probability $p_X(x)$ of assuming the value $x$. It will then have an expected value (mean) $\mu=\mathbb{E}(X)=\sum_xxp_X(x)$ and variance $\sigma^2=V(X)=\mathbb{E}(X^2)-(\mathbb{E}(X))^2=\sum_x(x-\mathbb{E}(X))^2p_X(x)$ where $\sigma$ is the standard deviation. If $X$ is instead continuous it will have a probability density function $f_X(x)$ and the sums above will instead be integrals with $p_X(x)$ replaced by $f_X(x)$.
|
||||
|
||||
Expectation is linear:
|
||||
\[\mathbb{E}(aX+bY) = a\mathbb{E}(X)+b\mathbb{E}(Y)\]
|
||||
For independent $X$ and $Y$, \[V(aX+bY) = a^2V(X)+b^2V(Y).\]
|
||||
|
||||
\subsubsection{Binomial distribution}
|
||||
The number of successes in $n$ independent yes/no experiments, each which yields success with probability $p$ is $\textrm{Bin}(n,p),\,n=1,2,\dots,\, 0\leq p\leq1$.
|
||||
\[p(k)=\binom{n}{k}p^k(1-p)^{n-k}\]
|
||||
\[\mu = np,\,\sigma^2=np(1-p)\]
|
||||
$\textrm{Bin}(n,p)$ is approximately $\textrm{Po}(np)$ for small $p$.
|
||||
|
||||
\subsubsection{First success distribution}
|
||||
The number of trials needed to get the first success in independent yes/no experiments, each which yields success with probability $p$ is $\textrm{Fs}(p),\,0\leq p\leq1$.
|
||||
\[p(k)=p(1-p)^{k-1},\,k=1,2,\dots\]
|
||||
\[\mu = \frac1p,\,\sigma^2=\frac{1-p}{p^2}\]
|
||||
|
||||
\subsubsection{Poisson distribution}
|
||||
The number of events occurring in a fixed period of time $t$ if these events occur with a known average rate $\kappa$ and independently of the time since the last event is $\textrm{Po}(\lambda),\,\lambda=t\kappa$.
|
||||
\[p(k)=e^{-\lambda}\frac{\lambda^k}{k!}, k=0,1,2,\dots\]
|
||||
\[\mu=\lambda,\,\sigma^2=\lambda\]
|
||||
|
||||
\subsubsection{Uniform distribution}
|
||||
If the probability density function is constant between $a$ and $b$ and 0 elsewhere it is $\textrm{U}(a,b),\,a<b$.
|
||||
\[f(x) = \left\{
|
||||
\begin{array}{cl}
|
||||
\frac{1}{b-a} & a<x<b\\
|
||||
0 & \textrm{otherwise}
|
||||
\end{array}\right.\]
|
||||
\[\mu=\frac{a+b}{2},\,\sigma^2=\frac{(b-a)^2}{12}\]
|
||||
|
||||
\subsubsection{Exponential distribution}
|
||||
The time between events in a Poisson process is $\textrm{Exp}(\lambda),\,\lambda>0$.
|
||||
\[f(x) = \left\{
|
||||
\begin{array}{cl}
|
||||
\lambda e^{-\lambda x} & x\geq0\\
|
||||
0 & x<0
|
||||
\end{array}\right.\]
|
||||
\[\mu=\frac{1}{\lambda},\,\sigma^2=\frac{1}{\lambda^2}\]
|
||||
|
||||
\subsubsection{Normal distribution}
|
||||
Most real random values with mean $\mu$ and variance $\sigma^2$ are well described by $\mathcal{N}(\mu,\sigma^2),\,\sigma>0$.
|
||||
\[ f(x) = \frac{1}{\sqrt{2\pi\sigma^2}}e^{-\frac{(x-\mu)^2}{2\sigma^2}} \]
|
||||
If $X_1 \sim \mathcal{N}(\mu_1,\sigma_1^2)$ and $X_2 \sim \mathcal{N}(\mu_2,\sigma_2^2)$ then
|
||||
\[ aX_1 + bX_2 + c \sim \mathcal{N}(\mu_1+\mu_2+c,a^2\sigma_1^2+b^2\sigma_2^2) \]
|
||||
1709
2025spring/source/Math/sphericalCoordinates.pdf
Normal file
1709
2025spring/source/Math/sphericalCoordinates.pdf
Normal file
File diff suppressed because it is too large
Load Diff
36
2025spring/source/Misc/FastI.cpp
Normal file
36
2025spring/source/Misc/FastI.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
#define getint(n) int n; read(n)
|
||||
#define getll(n) ll n; read(n)
|
||||
#define inta getint(a)
|
||||
#define intab getint(a); getint(b)
|
||||
char get() {
|
||||
static char buf[100000], *S=buf, *T=buf;
|
||||
if(S == T) {
|
||||
S = buf;T = buf + fread(buf, 1, 100000, stdin);
|
||||
if(S == T) return EOF;
|
||||
}
|
||||
return *S++;
|
||||
}
|
||||
void read(int& n) {
|
||||
n = 0;
|
||||
char c; bool neg = false;
|
||||
for(c = get(); c < '0'; c=get()) if(c=='-') neg = true;
|
||||
for(;c>='0';c=get()) n = n*10+c-'0';
|
||||
if(neg) n = -n;
|
||||
}
|
||||
void read(ll& n) {
|
||||
n = 0;
|
||||
char c; bool neg = false;
|
||||
for(c = get(); c < '0'; c=get()) if(c=='-') neg = true;
|
||||
for(;c>='0';c=get()) n = n*10+c-'0';
|
||||
if(neg) n = -n;
|
||||
}
|
||||
int read(char s[]) {
|
||||
char c; int p = 0;
|
||||
while((c = get()) <= ' ');
|
||||
|
||||
s[p++] = c;
|
||||
while((c = get()) >= ' ') s[p++] = c;
|
||||
s[p] = '\0';
|
||||
|
||||
return p;
|
||||
}
|
||||
0
2025spring/source/Misc/StressTest.sh
Normal file
0
2025spring/source/Misc/StressTest.sh
Normal file
7
2025spring/source/Misc/mt19937.cpp
Normal file
7
2025spring/source/Misc/mt19937.cpp
Normal file
@@ -0,0 +1,7 @@
|
||||
const long long rand_L = 1;
|
||||
const long long rand_R = 10;
|
||||
mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
|
||||
uniform_int_distribution<int> dist(rand_L, rand_R);
|
||||
auto gen = bind(dist, rng);
|
||||
|
||||
gen(); gen(); gen();
|
||||
92
2025spring/source/String/F_Z_M_SA_LCP.cpp
Normal file
92
2025spring/source/String/F_Z_M_SA_LCP.cpp
Normal file
@@ -0,0 +1,92 @@
|
||||
const int N = 1e5+7;
|
||||
char s[N];
|
||||
int F[N], Z[N], M[N];
|
||||
int sa[N]; int ord[N], tmp[N], cnt[N];
|
||||
int lcp[N];
|
||||
int main() {
|
||||
scanf("%s", s+1);
|
||||
int n = strlen(s+1);
|
||||
|
||||
// KMP - fail function {
|
||||
F[1] = 0; int j = 0;
|
||||
for(int i=2; i<=n;i++)
|
||||
{
|
||||
while(j > 0 and s[i] != s[j+1]) j = F[j];
|
||||
F[i] = j+=(s[i] == s[j+1]);
|
||||
}
|
||||
}
|
||||
|
||||
//Z - Z array {
|
||||
Z[1] = n; int j = 1, r = 0;
|
||||
for(int i=2; i<=n; i++)
|
||||
{
|
||||
Z[i] = i<j+r?min(Z[i-j+1], j+r-i):0;
|
||||
while(s[1+Z[i]] == s[i+Z[i]]) Z[i]++;
|
||||
if(j+r < i+Z[i]) j = i, r = Z[i];
|
||||
}
|
||||
}
|
||||
|
||||
//Manacher - M array {
|
||||
M[1] = 0; int j = 1, r = 0;
|
||||
for(int i=2; i<=n; i++)
|
||||
{
|
||||
M[i] = i<j+r?min(M[2*j-i], j+r-i):0;
|
||||
while(1 <= i-M[i]-1 && i+M[i]+1 <= n
|
||||
&& s[i-M[i]-1] == s[i+M[i]+1]) M[i]++;
|
||||
if(j+r < i+M[i]) j = i, r = M[i];
|
||||
}
|
||||
}
|
||||
|
||||
//Suffix Array - SA {
|
||||
int t = 1; ord[n+1] = 0; tmp[0] = 0; sa[0] = 0;
|
||||
|
||||
auto cmp = [&t, &n](int i,int j) {
|
||||
return ord[i] == ord[j]
|
||||
?ord[min(i+t, n+1)]<ord[min(j+t, n+1)]
|
||||
:ord[i]<ord[j];
|
||||
};
|
||||
|
||||
forr(i, n) ord[i] = s[i], sa[i] = i;
|
||||
sort(sa+1, sa+1+n, [](int i,int j){return ord[i]<ord[j];});
|
||||
|
||||
forr(i, n) tmp[sa[i]] = tmp[sa[i-1]] + (ord[sa[i-1]]<ord[sa[i]]);
|
||||
swap(tmp, ord);
|
||||
|
||||
while(t < n) {
|
||||
fors(i, 0, n) cnt[i] = 0;
|
||||
forr(i, n) cnt[ord[min(i+t, n+1)]]++;
|
||||
forr(i, n) cnt[i] += cnt[i-1];
|
||||
fore(i, n, 1) tmp[cnt[ord[min(i+t, n+1)]]--] = i;
|
||||
|
||||
fors(i, 0, n) cnt[i] = 0;
|
||||
forr(i, n) cnt[ord[i]]++;
|
||||
forr(i, n) cnt[i] += cnt[i-1];
|
||||
fore(i, n, 1) sa[cnt[ord[tmp[i]]]--] = tmp[i];
|
||||
|
||||
forr(i, n) tmp[sa[i]] = tmp[sa[i-1]] + cmp(sa[i-1], sa[i]);
|
||||
swap(ord, tmp);
|
||||
|
||||
t<<=1;
|
||||
if(ord[sa[n]] == n) break;
|
||||
}
|
||||
}
|
||||
|
||||
//LCP array {
|
||||
int k = 0;
|
||||
forr(i, n) if(ord[i] != 1) {
|
||||
int j = sa[ord[i]-1];
|
||||
while(s[i+k] == s[j+k]) k++;
|
||||
lcp[ord[i]] = k;
|
||||
|
||||
if(k > 0) k--;
|
||||
}
|
||||
}
|
||||
|
||||
printf("\nF : "); forr(i, n) printf("%d ", F[i]);
|
||||
printf("\nZ : "); forr(i, n) printf("%d ", Z[i]);
|
||||
printf("\nM : "); forr(i, n) printf("%d ", M[i]);
|
||||
printf("\nSA : "); forr(i, n) printf("%d ", sa[i]);
|
||||
printf("\nLCP : x "); fors(i, 2, n) printf("%d ", lcp[i]);
|
||||
|
||||
printf("\n"); forr(i, n) printf("%s\n", s+sa[i]);
|
||||
}
|
||||
17
2025spring/source/String/KMP.cpp
Normal file
17
2025spring/source/String/KMP.cpp
Normal file
@@ -0,0 +1,17 @@
|
||||
int fail[N]; // N : s의 최대 길이
|
||||
vi kmp(char obj[], char s[]) {
|
||||
vi ret;
|
||||
for(int i = 1, j = 0; s[i]; i++) {
|
||||
fail[i] = 0;
|
||||
while(j > 0 and s[i] != s[j]) j = fail[j-1];
|
||||
if(s[i] == s[j]) fail[i] = ++j;
|
||||
}
|
||||
for(int i = 0, j = 0; obj[i]; i++) {
|
||||
while(j > 0 and obj[i] != s[j]) j = fail[j-1];
|
||||
if(obj[i] == s[j]) {
|
||||
if(s[j+1]) j++;
|
||||
else ret.push_back(i-j), j = fail[j];
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
132
2025spring/source/String/std::string.cpp
Normal file
132
2025spring/source/String/std::string.cpp
Normal file
@@ -0,0 +1,132 @@
|
||||
/////////////////////////////////////////////////////////
|
||||
string s; //변수 선언
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
string s = "Hwan"; //output : Hwan
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
string s1("Hwan"); //output ㄷ: Hwan
|
||||
string s2(4, 'A'); //output : AAAA
|
||||
string s3(s1, 0, s1.length() - 2); //output : HW
|
||||
string s4(s1, 2, s1.length()); //output : an
|
||||
string s5(s2); //output : AAAA
|
||||
string s6("ABCDE", 3); //output : ABC
|
||||
|
||||
char c[] = "TEST Code!!";
|
||||
string s7(c); //output : TEST Code!!
|
||||
/////////////////////////////////////////////////////////
|
||||
string s = "ABCDE123";
|
||||
|
||||
cout << s.at(2) << endl; //output : C (범위가 맞지 않으면 예외처리를 함)
|
||||
cout << s[0] << endl; //output : A
|
||||
cout << s.front() << endl; //output : A
|
||||
cout << s.back() << endl; //output : 3
|
||||
|
||||
const char * c = s.c_str(); //배열로써 접근이 가능하며 '\0'에 접근이 가능하다.
|
||||
|
||||
cout << c << endl; //output : ABCDE123
|
||||
|
||||
cout << (c_arr == s) ? true : false; //output : 1(true)
|
||||
cout << (&(c_arr[0]) == &(s[0])) ? true : false; //output : 1(true)
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
string s = "ABCDE123";
|
||||
string::iterator iter = s.begin();
|
||||
string r_s, cp;
|
||||
|
||||
for (; iter != s.end(); iter++) {
|
||||
cout << *iter;
|
||||
if (*iter == 'E')
|
||||
break;
|
||||
} //output : ABCDE
|
||||
|
||||
|
||||
copy(s.rbegin(), s.rend(), back_inserter(r_s));
|
||||
copy(s.begin(), s.end(), back_inserter(cp));
|
||||
|
||||
cout << r_s << endl; //output : 321EDCBA
|
||||
cout << (s == r_s) ? true : false; //output : 0(false)
|
||||
cout << (s == cp) ? true : false; //output : 1(true)
|
||||
cout << (&(s[0]) == &(cp[0])) ? true : false; //output : 0(false)
|
||||
/////////////////////////////////////////////////////////
|
||||
string s = "ABCDE123"
|
||||
|
||||
s.insert(0, "TEST"); //output : TESTABCDE123
|
||||
s.insert(s.begin() + s.find_first_of('D') + 1, ':'); // output : TESTABCD:123(문자만 가능)
|
||||
|
||||
|
||||
////////// (compare) s = TESTABCD:123 /////////////
|
||||
s.compare("TESTABCD:123"); //output : 0
|
||||
s.compare("a"); //output : -1
|
||||
s.compare("X"); //output : -1
|
||||
s.compare("BBBBBBBBBBBBBBB"); //output : 1
|
||||
s.compare("100000000000000000000000"); //output : 1
|
||||
s.compare("VVVVV"); //output : -1
|
||||
|
||||
|
||||
////////// (erase) s = TESTABCD:123 /////////////
|
||||
s.erase(0, 4); //output : ABCD:123
|
||||
s.erase(find(s.begin(), s.end(), 'D')); //output : ABC:123('D'만 지움)
|
||||
s.erase(s.find(':')); //output : ABC(':'부터 뒤 문자까지 모두 지움)
|
||||
|
||||
|
||||
////////// (push, pop) s = ABC /////////////
|
||||
s.push_back('S'); //output : ABCS
|
||||
s.pop_back(); //output : ABC
|
||||
|
||||
|
||||
////////// (append) s = ABC /////////////
|
||||
s.append("TEST"); //output : ABCTEST
|
||||
s.append(1, '1'); //output : ABCTEST1
|
||||
s.append("123456789", 3, 3); //output : ABCTEST1456
|
||||
|
||||
|
||||
////////// (clear) s = ABCTEST1456 /////////////
|
||||
const char c[] = "Hwan";
|
||||
s.append(c); //output : ABCTEST1456Hwan
|
||||
s += c; //output : ABCTEST1456HwanHwan(capacity() = 15 -> 31)
|
||||
s.clear(); //s.size() = 0, s.capacity() = 31
|
||||
|
||||
|
||||
////////// (replace) s = '' /////////////
|
||||
s.append("ABCD123"); //output : ABCD123
|
||||
s.replace(4, 2, "Hwan"); //output : ABCDHwan3
|
||||
s.replace(s.find('H'), s.size() - s.find('H'), "WOW"); //output : ABCDWOW
|
||||
|
||||
|
||||
////////// (substr) s = ABCDWOW /////////////
|
||||
string temp = s.substr(4); //output : WOW;
|
||||
temp = s.substr(3, 2); //output : DW;
|
||||
temp = s.substr(s.size() - 3, 50); //output : WOW;
|
||||
|
||||
|
||||
////////// (copy) s = ABCDWOW /////////////
|
||||
char arr[5]{};
|
||||
s.copy(arr, sizeof arr - 1); //output : ABCD (마지막 '\n' 포함)
|
||||
|
||||
|
||||
////////// (resize) s = ABCDWOW /////////////
|
||||
s.resize(100); //output : ABCDWOW, s.size() = 100, s.capacity() = 111
|
||||
s.resize(4); //output : ABCD, s.size() = 4, s.capacity() = 15
|
||||
|
||||
|
||||
////////// (swap) s = ABCD /////////////
|
||||
string sw = "AAA";
|
||||
s.swap(sw); //s = "AAA", sw = "ABCD"
|
||||
|
||||
|
||||
/////////// c++ 20 ///////////////////
|
||||
s = "hello Hwan";
|
||||
s.starts_with("hello"); //output : true;
|
||||
s.starts_with('h'); //output : true;
|
||||
s.starts_with("Hwan"); //output : false;
|
||||
s.starts_with('x'); //output : false;
|
||||
|
||||
s.ends_with("Hwan"); //output : true;
|
||||
s.ends_with('n'); //output : true;
|
||||
s.ends_with("hello"); //output : false;
|
||||
s.ends_with('q'); //output : false;
|
||||
34
2025spring/source/Tree/Centroid.cpp
Normal file
34
2025spring/source/Tree/Centroid.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
vi adj[N]; bool cent[N];
|
||||
int sz[N], par[N];
|
||||
|
||||
void getSz(int s){
|
||||
sz[s] = 1;
|
||||
for(auto i:adj[s]){
|
||||
if(cent[i]) continue;
|
||||
if(par[s] == i) continue;
|
||||
par[i] = s; getSz(i); par[i] = 0;
|
||||
|
||||
sz[s] += sz[i];
|
||||
}
|
||||
}
|
||||
int getCent(int s, int n){
|
||||
for(auto i:adj[s])
|
||||
if(!cent[i] and sz[i] < sz[s] and sz[i] > n/2)
|
||||
return getCent(i, n);
|
||||
return s;
|
||||
}
|
||||
|
||||
int cpar[N];
|
||||
int getCentTree(int s){
|
||||
getSz(s);
|
||||
int C = getCent(s, sz[s]);
|
||||
cent[C] = true;
|
||||
for(auto i:adj[C]){
|
||||
if(cent[i]) continue;
|
||||
int c = getCentTree(i);
|
||||
cpar[c] = C;
|
||||
}
|
||||
return C;
|
||||
}
|
||||
|
||||
int C = getCentTree(1); cpar[C] = -1;
|
||||
76
2025spring/source/Tree/HLD.cpp
Normal file
76
2025spring/source/Tree/HLD.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
BOJ 트리와 쿼리 1
|
||||
1 i c: i번 간선의 비용을 c로 바꾼다.
|
||||
2 u v: u에서 v로 가는 단순 경로에 존재하는 비용 중에서 가장 큰 것을 출력한다.
|
||||
|
||||
const int N = 1e5+7;
|
||||
|
||||
vi adj[N]; int par[N]; int sz[N]; int d[N];
|
||||
void dfs1(int s) {
|
||||
sz[s] = 1;
|
||||
for(int i=0;i<adj[s].size();i++)
|
||||
if(adj[s][i] == par[s])
|
||||
{adj[s].erase(adj[s].begin() + i); break;}
|
||||
for(auto &i : adj[s]) {
|
||||
par[i] = s; d[i] = d[s] + 1;
|
||||
dfs1(i);
|
||||
sz[s] += sz[i];
|
||||
if(sz[i] > sz[adj[s][0]]) swap(adj[s][0], i);
|
||||
}
|
||||
}
|
||||
int in[N], c; int top[N];
|
||||
void dfs2(int s) {
|
||||
in[s] = ++c;
|
||||
for(auto i : adj[s]) {
|
||||
if(i == adj[s][0])
|
||||
top[i] = top[s];
|
||||
else top[i] = i;
|
||||
|
||||
dfs2(i);
|
||||
}
|
||||
}
|
||||
|
||||
Node *root; // Segment Tree
|
||||
int query(int a,int b) {
|
||||
int ans = 0;
|
||||
while(top[a] != top[b]) {
|
||||
if(d[top[a]] > d[top[b]]) swap(a, b);
|
||||
ans = max(ans, query(root, in[top[b]], in[b]));
|
||||
b = par[top[b]];
|
||||
}
|
||||
|
||||
if(d[a] > d[b]) swap(a, b);
|
||||
ans = max(ans, query(root, in[a]+1, in[b]));
|
||||
|
||||
return ans;
|
||||
}
|
||||
map<pii, int> m;
|
||||
int arr[N]; pii edge[N];
|
||||
int main() {
|
||||
getint(n);
|
||||
forr(i, n-1) {
|
||||
intab; adj[a].pb(b); adj[b].pb(a);
|
||||
getint(c);
|
||||
m[{a,b}] = m[{b, a}] = c;
|
||||
edge[i] = {a,b};
|
||||
}
|
||||
|
||||
dfs1(1); dfs2(1);
|
||||
forr(i, n) arr[in[i]] = m[{par[i], i}];
|
||||
root = new Node(1, n); init(root, arr);
|
||||
|
||||
getint(Q);
|
||||
while(Q--) {
|
||||
getint(q);
|
||||
if(q == 1) {
|
||||
getint(i); getint(c);
|
||||
auto [a, b] = edge[i];
|
||||
if(par[b] == a) a = b;
|
||||
|
||||
update(root, in[a], c, true);
|
||||
}
|
||||
if(q == 2) {
|
||||
intab;
|
||||
printf("%d\n", query(a, b));
|
||||
}
|
||||
}
|
||||
}
|
||||
0
2025spring/source/empty.cpp
Normal file
0
2025spring/source/empty.cpp
Normal file
7
2025spring/source/qwerty.cpp
Normal file
7
2025spring/source/qwerty.cpp
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma GCC optimize("O3")
|
||||
#pragma GCC optimize("Ofast")
|
||||
#pragma GCC optimize("unroll-loops")
|
||||
|
||||
#define endl '\n'
|
||||
#define foreach(i, l, r) for(ll i=(l); i<=(r); i++)
|
||||
#define forreach(i, l, r) for(ll i=l; i>=(r); i--)
|
||||
110
2025spring/teamnote.sty
Normal file
110
2025spring/teamnote.sty
Normal file
@@ -0,0 +1,110 @@
|
||||
\ProvidesPackage{teamnote}
|
||||
|
||||
\usepackage[left=1cm,right=1cm,top=2cm,bottom=1cm,a4paper]{geometry}
|
||||
\usepackage{fancyhdr}
|
||||
\usepackage{lastpage}
|
||||
\usepackage{ifthen}
|
||||
\usepackage{minted}
|
||||
\usepackage{color}
|
||||
\usepackage{indentfirst}
|
||||
\usepackage{amssymb}
|
||||
\usepackage{amsmath}
|
||||
\usepackage{import}
|
||||
\usepackage{caption}
|
||||
\usepackage[table,xcdraw]{xcolor}
|
||||
\usepackage[T1]{fontenc}
|
||||
\usepackage{setspace}
|
||||
|
||||
\setstretch{1} % No line-spacing
|
||||
|
||||
\renewcommand{\@listI}{% No spacing on list
|
||||
\leftmargin=25pt
|
||||
\rightmargin=0pt
|
||||
\labelsep=5pt
|
||||
\labelwidth=20pt
|
||||
\itemindent=0pt
|
||||
\listparindent=0pt
|
||||
\topsep=0pt plus 2pt minus 4pt
|
||||
\partopsep=0pt plus 1pt minus 1pt
|
||||
\parsep=0pt plus 1pt
|
||||
\itemsep=\parsep}
|
||||
|
||||
\setlength{\columnseprule}{0.4pt}
|
||||
\pagenumbering{arabic}
|
||||
\setminted{breaklines=true, tabsize=2, breaksymbolleft=}
|
||||
\usemintedstyle{perldoc}
|
||||
|
||||
\newcommand{\revised}{Should be \textcolor{red}{\textbf{revised}}.}
|
||||
\newcommand{\tested}{Should be \textcolor{red}{\textbf{tested}}.}
|
||||
\newcommand{\added}{Should be \textcolor{red}{\textbf{added}}.}
|
||||
\newcommand{\WIP}{\textcolor{red}{\textbf{Working in progress.}}}
|
||||
|
||||
\newcommand{\schoolname}{Some University}
|
||||
\newcommand{\teamname}{Some Teamname}
|
||||
\newcommand{\authorname}{Some Members}
|
||||
|
||||
\newcommand{\maketitlepage}{\maketitle
|
||||
|
||||
\tableofcontents
|
||||
|
||||
\thispagestyle{fancy}
|
||||
|
||||
}
|
||||
\DeclareRobustCommand{\teamnote}[3]{
|
||||
\renewcommand{\schoolname}{#1}
|
||||
\renewcommand{\teamname}{#2}
|
||||
\renewcommand{\authorname}{#3}
|
||||
}
|
||||
\pagestyle{fancy}
|
||||
\lhead{\schoolname{} -- \teamname}
|
||||
\rhead{Page \thepage{} of
|
||||
\ifthenelse{\pageref{LastPage} < 26}{\pageref{LastPage}}{\textcolor{red}{\textbf{\pageref{LastPage}}}}}
|
||||
\fancyfoot{}
|
||||
|
||||
\title{Team Note of \teamname}
|
||||
\author{\authorname}
|
||||
\date{Compiled on \today}
|
||||
|
||||
|
||||
|
||||
|
||||
\newboolean{BangShowUsage}
|
||||
\setboolean{BangShowUsage}{false}
|
||||
\newcommand{\ShowUsage}{\setboolean{BangShowUsage}{false}}
|
||||
\newcommand{\HideUsage}{\setboolean{BangShowUsage}{true}}
|
||||
|
||||
|
||||
\newboolean{BangShowComplexity}
|
||||
\setboolean{BangShowComplexity}{false}
|
||||
\newcommand{\ShowComplexity}{\setboolean{BangShowComplexity}{false}}
|
||||
\newcommand{\HideComplexity}{\setboolean{BangShowComplexity}{true}}
|
||||
|
||||
|
||||
\newboolean{BangShowAuthor}
|
||||
\setboolean{BangShowAuthor}{false}
|
||||
\newcommand{\ShowAuthor}{\setboolean{BangShowAuthor}{false}}
|
||||
\newcommand{\HideAuthor}{\setboolean{BangShowAuthor}{true}}
|
||||
|
||||
\newcommand{\Algorithm}[6]{
|
||||
\subsection{#1}
|
||||
|
||||
\ifthenelse{\equal{#2}{} \OR \boolean{BangShowUsage}}{}{\textbf{Usage:} #2}
|
||||
|
||||
\ifthenelse{\equal{#3}{} \OR \boolean{BangShowComplexity}}{}{\textbf{Time Complexity:} #3}
|
||||
|
||||
\ifthenelse{\equal{#6}{} \OR \boolean{BangShowAuthor}}{}{\textbf{Author:} #6}
|
||||
|
||||
\ifthenelse{\equal{#5}{}}{}{\ifthenelse{\equal{#4}{}}{\inputminted[]{cpp}{#5}}{\inputminted[]{#4}{#5}}}
|
||||
}
|
||||
|
||||
\newcommand{\SubAlgorithm}[6]{
|
||||
\subsubsection{#1}
|
||||
|
||||
\ifthenelse{\equal{#2}{} \OR \boolean{BangShowUsage}}{}{\textbf{Usage:} #2}
|
||||
|
||||
\ifthenelse{\equal{#3}{} \OR \boolean{BangShowComplexity}}{}{\textbf{Time Complexity:} #3}
|
||||
|
||||
\ifthenelse{\equal{#6}{} \OR \boolean{BangShowAuthor}}{}{\textbf{Author:} #6}
|
||||
|
||||
\ifthenelse{\equal{#5}{}}{}{\ifthenelse{\equal{#4}{}}{\inputminted[]{cpp}{#5}}{\inputminted[]{#4}{#5}}}
|
||||
}
|
||||
Reference in New Issue
Block a user