teamnote history merge

This commit is contained in:
2026-06-03 09:36:52 +09:00
parent f50ed902fe
commit 7176febe54
142 changed files with 13243 additions and 0 deletions

BIN
2025spring/main.pdf Normal file

Binary file not shown.

939
2025spring/main.tex Normal file
View 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}

View 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);
}

View 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;
}

View 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;
}
};

View 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]);
}

View 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

View 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;
}

View 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);
}
}
}

View 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] 선택

View 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>;

View 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);
}
}
};

View 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();
}
};

View 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>;

View 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;
}
}

View 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;
};

View 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;
}

View 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;

View 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;
}

View 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);
}

View 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};
}

View 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);

View 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;
}
};

View 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};
}

View 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};
}

View 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;
}

View 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);
}

View 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;
}

View 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;
}

View 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

View 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;
}

View 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

View 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;
}
}

View 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;
}

View 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) \]

File diff suppressed because it is too large Load Diff

View 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;
}

View File

View 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();

View 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]);
}

View 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;
}

View 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;

View 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;

View 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));
}
}
}

View File

View 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
View 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}}}
}