Randomization Techniques

Overview

Prerequisites: Random functions and Introduction to probability

This article gives a brief classification of randomization techniques related to OI/ICPC and introduces each category. It also introduces some methods that are rarely used in OI/ICPC but are relatively close to OI/ICPC in style and other respects; these are marked with (*) beforehand.

This classification does not represent a broad consensus and certainly cannot cover every possibility, so it is provided for reference only.

Notation and conventions:

  • Pr[A]\mathrm{Pr}[A] denotes the probability that event AA occurs.
  • E[X]\mathrm{E}[X] denotes the expectation of random variable XX.
  • The assignment symbol :=:= introduces a new quantity; for example, Y:=1926Y:=1926 introduces a quantity with value 19261926, namely YY.

Covering target elements with random sets

There is one or more solution in a huge solution space that we want. We can try casting a net repeatedly; as long as we catch the target solution once, we succeed.

Example: Testing whether a graph is tripartite

Problem

Given a simple undirected graph with nn vertices and mm edges, color every vertex with one of the three colors RGB so that every pair of adjacent vertices has a different color, or report that no solution exists.

For each vertex vv, independently choose a color from {R,G,B}\{R,G,B\}, denoted CvC_v, and stipulate that vv is not colored CvC_v. The probability that an optimal solution happens to satisfy these restrictions is clearly (23)n\big(\frac 23\big)^n.

Under these restrictions, for a pair of adjacent vertices (u,v)(u,v), the requirement that u,vu,v have different colors is equivalent to the following implication:

  • For every color other than Cu,CvC_u,C_v, denoted XX, if uu is colored XX, then vv is colored {R,G,B}∖{X,Cv}\{R,G,B\}\setminus\{X,C_v\}.

Thus, for each vv we can set a Boolean variable BvB_v, whose value indicates which of the two remaining colors is assigned to vv. The problem can then be solved with a 2-SAT model in O(n+m)O(n+m) time.

This gives a success probability of (23)n\big(\frac 23\big)^n for one run. Run the algorithm −(32)nlog⁡ϵ-\big(\frac 32\big)^n\log \epsilon times and output a solution if any run succeeds; this guarantees a success probability of 1−ϵ1-\epsilon. (See the later section on the analysis of probability bounds for details.)


Review: In this problem, the “solution space” is the set {R,G,B}n\{R,G,B\}^n. Each time, we search for the “target solution”—a valid coloring—within a smaller range by imposing random restrictions.

Example: CodeChef SELEDGE

Brief problem statement

Given an undirected graph whose vertices and edges have nonnegative weights, find an edge set of size ≤K\leq K, denoted SS, that maximizes the sum of the weights of vertices incident to SS minus the sum of the weights of edges in SS. The weight of a vertex is counted only once.

Observation: if three selected edges form a path, deleting the middle edge is never worse; if several selected edges form a cycle, deleting any one of them is never worse.

Corollary: the edge set selected by an optimal solution must form several vertex-disjoint stars (that is, trees of diameter at most two).

Corollary: the edge set selected by an optimal solution must form a bipartite graph.

Independently color every vertex black or white with equal probability, and require this coloring to be exactly the black-and-white coloring of the bipartite graph corresponding to the optimal solution.

Let us calculate the probability that the optimal solution satisfies this requirement:

  • Consider a star with nn vertices. It clearly has two coloring schemes, so the probability that it receives the correct colors is 22n=21−n\dfrac 2{2^n}=2^{1-n}.
  • Suppose the numbers of vertices in the stars of the optimal solution are a1,⋯ ,ala_1,\cdots,a_l. Then (a1−1)+⋯+(al−1)≤K(a_1-1)+\cdots+(a_l-1)\leq K, where KK is the maximum number of edges that can be selected.
  • Therefore, the probability that all stars receive the correct colors is 21−a1⋯21−al≥2−K2^{1-a_1}\cdots 2^{1-a_l}\geq 2^{-K}.

Under these restrictions, try to build a min-cost flow model to calculate the optimal answer:

  • Build a bipartite graph, with white vertices on the left connected to SS and black vertices on the right connected to TT.
    • For a white vertex vv, add an edge from SS to it with capacity 1 and cost −Av-A_v, and an edge with capacity ∞\infty and cost 0.
    • For a black vertex vv, add an edge from it to TT with capacity 1 and cost −Av-A_v, and an edge with capacity ∞\infty and cost 0.
  • For an edge (u,v,B)(u,v,B) in the original graph with uu white and vv black, add an edge from uu to vv with capacity 1 and cost BB.
  • Restrict the flow in this graph to be at most KK; the opposite of the minimum cost is then the answer.

If we solve this with min-cost flow using SPFA, the complexity is O(K2(n+m))O\big(K^2(n+m)\big). Proof:

  • First, the number of SPFA runs is clearly ≤K\leq K.
  • Then, during one SPFA run, any vertex is enqueued at most O(K)O(K) times. This is because:
    • At any moment there are at most 3K3K edges carrying flow; otherwise, more than KK edges would have been selected in the original graph.
    • For any augmenting path of length LL, at least L2−2\dfrac L2-2 edges are reverse edges of some edge carrying flow, because all forward edges point from the left side of the graph to the right side, and only these reverse edges can point from right to left.
    • Combining the two facts, the length of any augmenting path is at most 6K+46K+4.
  • Therefore, the complexity is O(K2(n+m))O\big(K^2(n+m)\big).

As in the previous problem, we need to repeat the entire process −2Klog⁡ϵ-2^K \log\epsilon times to obtain a success probability of 1−ϵ1-\epsilon. The total complexity is O(2KK2(n+m)⋅−log⁡ϵ)O\big(2^KK^2(n+m)\cdot -\log\epsilon\big).

Hitting a target set with random elements

We need to determine an arbitrary element of a set, so we randomly select elements in the hope of hitting this set exactly.

Example: Gym 101550I

Brief problem statement

The graph consists of two parallel chains and two parallel edges connecting the chains. Given several simple paths in this graph, each representing a phone call, choose as few edges as possible on which to place wiretaps so that every given path contains at least one wiretap.

The entire graph can be decomposed into a cycle and four chains extending from the cycle. For any one of these four chains, denoted CC, a greedy algorithm can easily find a placement of wiretaps on the chain satisfying the following conditions:

  • Under the condition that all calls entirely within CC are intercepted, use the fewest possible wiretaps.
  • Under the previous condition, make the minimum distance from the wiretaps on CC to the cycle as small as possible.
    • The purpose of this requirement is to intercept as many calls as possible with exactly one endpoint inside CC.

Next consider the four edges where the chains meet the cycle. We can brute-force whether to place a wiretap on each of these edges. Clearly, if we want to intercept calls crossing between a chain and the cycle, placing a wiretap on one of these four edges is optimal. We can now divide the call paths into the following types:

  1. Call paths entirely on a chain. These paths have already been intercepted, so they can be ignored.
  2. Call paths crossing between a chain and the cycle that have already been intercepted. They can be ignored.
  3. Call paths crossing between a chain and the cycle that have not been intercepted. We can cut off their chain portions directly (because the wiretap placement on the chains is fixed) and retain only their cycle portions.
  4. Call paths entirely on the cycle.

The problem has now been reduced to a problem on the cycle.

Suppose the optimal solution places wiretaps on the edge set SS. If we have identified any element of SS, say ee, we can:

  • First break the cycle at ee to form a chain.
  • Then start at ee and proceed greedily, repeatedly finding the next edge on which to place a wiretap. With suitable preprocessing, each greedy step can be performed in O(1)O(1) time.
  • Thus solve the problem in O(∣S∣)O(|S|) time.

We randomly choose an edge e′e' on the cycle, stipulate that e′∈Se'\in S, and then perform the process above, repeating it several times and taking the best result.

Analyze the complexity of one run:

  • Observation: let S′S' denote the optimal solution among all solutions that select e′e'. Then ∣S′∣≤∣S∣+1|S'|\leq |S|+1.
  • Therefore, the complexity of one run is O(∣S′∣)=O(∣S∣)O(|S'|)=O(|S|).

Analyze the success probability:

  • Clearly, the success probability of one run is ∣S∣n\dfrac {|S|}n, where nn is the length of the cycle.
  • Therefore, we need to repeat the process −n∣S∣log⁡ϵ-\dfrac n{|S|}\log\epsilon times to obtain a success probability of 1−ϵ1-\epsilon.

In conclusion, the complexity of the algorithm is O(∣S∣⋅−n∣S∣log⁡ϵ)=O(−nlog⁡ϵ)O\big(|S|\cdot -\dfrac n{|S|}\log\epsilon\big)=O(-n\log\epsilon).

Example: CSES 1685 New Flight Routes

Brief problem statement

Given a directed graph, add as few edges as possible to make it strongly connected. You must output a construction.

First condense the original graph into strongly connected components. Our goal is clearly to make every sink reachable from every source.

It is not difficult to prove that we only need to add edges from sinks to sources, because any other added edge can be replaced by an edge from a sink to a source that is no worse.

One core operation is to take a sink tt and a source ss (they need not belong to the same weakly connected component), and add an edge t→st\to s to make both ss and tt cease to be sinks or sources (call this Goal I). Ideally, each operation reduces the number of sinks and sources by one. We continue until only one sink or only one source remains, which is a trivial case. Thus we conjecture that the answer is the larger of the number of sources and the number of sinks.

It is not difficult to see that the necessary and sufficient condition for the operation above to achieve Goal I is that tt has a predecessor other than ss, and ss has a successor other than tt. It can be proved (as we will show shortly) that every DAG with at least two sources and at least two sinks contains such an (s,t)(s,t), but this existence result does not help us construct a solution; further analysis is needed.

  • Even with this necessary and sufficient condition, it is difficult to obtain an algorithm directly, mainly because adding the edge t→st\to s may affect the validity of other pairs (s′,t′)(s',t'), which is difficult to handle.

We know little about the relationships between sources and sinks (we may not even be able to quickly query whether a pair s−ts-t is reachable without DFS + bitset preprocessing, which the time limit does not allow). This suggests that we need some very general and powerful property.

Observation: pairs (s,t)(s,t) that do not satisfy Goal I number at most n+m−1n+m-1, where nn is the number of sources and mm is the number of sinks.

  • Reason: if each such (s,t)(s,t) is viewed as an edge joining s,ts,t, all these edges form a graph consisting of several vertex-disjoint paths, so the number of edges is no more than the number of vertices minus one.
  • The motivation for this observation is that, to apply an existence result in an algorithm, a qualitative conclusion often first needs to be strengthened into a quantitative one.

Corollary: if (s,t)(s,t) is chosen uniformly at random, the probability that it satisfies the preceding requirement is at least ≥(n−1)(m−1)nm\geq \dfrac {(n-1)(m-1)}{nm}.

  • Notice that this conclusion is strictly stronger than the existence result given earlier.

Corollary: choose min⁡(n,m)2\dfrac {\min(n,m)}2 pairs (s,t)(s,t) without common elements independently and uniformly at random, and perform the corresponding operations in order (that is, add the edges t→st\to s). Then the probability that all these operations satisfy Goal I is at least ≥14\geq \dfrac 14.

  • Reason:
= (n−1)(m−1)nm⋅(n−2)(m−2)(n−1)(m−1)⋯(n−k)(m−k)(n−k+1)(m−k+1)=(n−k)(m−k)nm≥14\begin{aligned} &\phantom{=\ }\dfrac {(n-1)(m-1)}{nm}\cdot\dfrac{(n-2)(m-2)}{(n-1)(m-1)}\cdots\dfrac{(n-k)(m-k)}{(n-k+1)(m-k+1)}\\ &=\dfrac{(n-k)(m-k)}{nm}\\ &\geq \dfrac 14 \end{aligned}

After selecting kk pairs (s,t)(s,t) consecutively, it is easy to check whether they all satisfy Goal I: run strongly connected component condensation once more and check whether n,mn,m have both decreased by kk. If each round reduces k=min⁡(n,m)2k=\dfrac{\min(n,m)}2, then min⁡(n,m)\min(n,m) must become 1 within O(log⁡(n+m))O\big(\log(n+m)\big) rounds, reducing the problem to the trivial case.

Algorithm pseudocode
while(n>1 and m>1):
    randomly choose k=min(n,m)/2 pairs (s,t)
    add edge t->s for all these pairs
    if new_n>n-k or new_m>m-k:
        roll_back()
solve_trivial()

The complexity is O((∣V∣+∣E∣)log⁡∣V∣)O\big((|V|+|E|) \log |V|\big).


Review: We need to determine any pair (s,t)(s,t) that can achieve Goal I, so we randomly choose (s,t)(s,t).

Using randomization to obtain properties of random data

If the data of a problem is generated randomly, we may be able to use properties of random data to solve it. In some cases, even if the data is not randomly generated, we can use randomization to give it some characteristics of random data, thereby helping to solve the problem.

Example: Randomized incremental method

A randomly generated sequence of elements may have properties such as a small expected number of changes in the prefix optimum, and the randomized incremental method obtains such properties by randomly shuffling the input sequence.

See randomized incremental method for details.

Example: randomized solution for TopCoder MagicMolecule

Brief problem statement

Given an undirected graph with nn vertices and vertex weights, among all cliques of size at least 2n3\dfrac {2n}3, find one with maximum total vertex weight.

n≤50n\leq 50

A meet-in-the-middle search is natural. Split the vertex set evenly into two halves VL,VRV_L,V_R, both of size n2\dfrac n2. Compute an array fL,kf_{L,k} giving the maximum total weight of all cliques in the vertex set L⊆VLL\subseteq V_L having size ≥k\geq k. Then enumerate every clique CRC_R in the right half, find the vertices in the left half adjacent to every vertex in CRC_R (call this vertex set NLN_L), and update the answer with fNL,23n−∣CR∣+value(CR)f_{N_L,\frac 23 n-|C_R|}+\textit{value}(C_R).

  • Notice that an O(1)O(1)-time transition is possible for every fL,kf_{L,k}. Specifically, choose an arbitrary element dd of LL and consider cases:
    • If dd is not in the optimal clique, transition from fL∖{d},kf_{L\setminus \{d\},k}.
    • If dd is in the optimal clique, transition from fL∩N(d),k+value(d)f_{L\cap N(d),k}+\textit{value}(d), where N(d)N(d) denotes the set of neighbors of dd.
    • Do not forget to use fL,k+1f_{L,k+1} to update fL,kf_{L,k}.

This solution is too slow. Try to optimize it:

  • Split the vertex set uniformly at random. Then, with appreciable probability, the vertex set CresC_{res} of the optimal solution is also split exactly evenly, namely ∣Cres∩VL∣=∣Cres∩VR∣|C_{res}\cap V_L|=|C_{res}\cap V_R|.
    • Of course, ∣Cres∣|C_{res}| may be odd. For simplicity, assume it is even here; the odd case does not fundamentally change the solution.
    • Experiments show that about 20 random trials give a high probability of satisfying this property at least once. In other words, if our algorithm relies on CresC_{res} being split evenly, repeating the algorithm 20 times and taking the best result likewise gives a high probability of obtaining the correct answer.
  • With this property, we can stipulate directly that the left clique LL and right clique CRC_R both have size ≥n3\geq \dfrac n3. This improves the complexity in two ways:
    • ff no longer needs to record the size dimension.
    • Since we only need to consider cliques of size ≥n3\geq \dfrac n3, the number of left cliques LL and right cliques CRC_R to consider is greatly reduced, to about 1.8⋅1061.8\cdot 10^6.
  • The bottleneck now becomes finding the weight sum of a particular subset on one side, because this requires O(2∣VL∣+2∣VR∣)O\big(2^{|V_L|}+2^{|V_R|}\big) preprocessing.
    • Solution: split VL,VRV_L,V_R in half again. When querying the weight sum of a subset, split that subset into two halves, query each half, and add the answers.
  • This is enough to solve the problem.

Review: A random set has the property that the sizes of the two parts into which it is split do not differ too greatly, and we obtain this property by randomly splitting the set.

Randomization for hashing

Example: UOJ #207 Covalent Grandpa Visits Changsha

Brief problem statement

Maintain a dynamically changing tree and a dynamically changing set of vertex pairs. You need to support:

  • Delete and add edges, while guaranteeing that the result remains a tree.
  • Add or delete a vertex pair.
  • Given an edge ee, determine whether, for every vertex pair (s,t)(s,t) in the set, ee lies on the simple path between s,ts,t.

For every edge ee in the graph, define SeS_e as the set of important paths passing through that edge (that is, the (a,b)(a,b) pairs in the problem). Consider dynamically maintaining the hash value of each set SeS_e. Then it is easy to determine whether SeS_e equals the universal set, that is, whether ee is an “unavoidable path”.

To hash the sets, assign each (a,b)(a,b) a random nonnegative integer less than 2642^{64}, denoted H(a,b)H_{(a,b)}. The hash value of a set is the XOR of the HH values of its elements.

Then the hash value of any fixed set is uniformly distributed over R:={0,1,⋯ ,264−1}R:=\left\{0,1,\cdots,2^{64}-1\right\} (in other words, the hash value ranges over RR and every value has the same probability). This is because:

  1. A single H(a,b)H_{(a,b)} is clearly uniformly distributed.
  2. The XOR of two independent random variables that are both uniformly distributed over RR is also uniformly distributed over RR. This is not difficult to prove.

Thus the correctness probability of the algorithm is guaranteed.

As for maintaining this hash value, an LCT suffices.

Example: CodeChef PANIC and analysis of its error rate

The rough solution to this problem is:

  1. It can be proved1 that S(N)S(N), with respect to NN, satisfies an O(K)O(K)-order linear recurrence.
  2. Use the BM algorithm to find this recurrence.
  3. Use the recurrence and the Cayley–Hamilton theorem to calculate S(N)S(N).

Here we focus only on the second part, namely how to find a recurrence for a sequence of matrices. Thus we only need to consider the following problem:

Problem

Given a sequence of matrices that satisfies a homogeneous linear recurrence modulo P:=998244353P:=998244353 (scalar multiplication and addition in the recurrence are defined as matrix scalar multiplication and addition), find the shortest recurrence.

If a sequence of matrices satisfies a recurrence FF, then each of its entries also satisfies FF. However, if we find a shortest recurrence F′F' for one entry, F′F' may be shorter than FF, causing a problem.

Solution: assign each matrix entry (i,j)(i,j) a $ [!note]+ Brief problem statement

Given two directed graphs G0,G1G_0,G_1 whose edge labels are lowercase letters, compute for each graph the multiset of strings corresponding to all paths (possibly an infinite multiset), and determine whether the two multisets are equal. If they are not equal, output a shortest string whose occurrence counts in the two multisets differ.

Let fK,i,jf_{K,i,j} denote the hash value of the multiset of all strings corresponding to paths in graph GKG_K that start at vertex ii and have length jj. Consider every state in increasing order of jj; when transitioning, enumerate the outgoing edges of ii and stipulate that the chosen edge is the first edge of the path.

To determine whether a bad string of length =L=L exists, it suffices to integrate and compare {f0,∗,L}\{f_{0,*,L}\} and {f1,∗,L}\{f_{1,*,L}\} separately (the wildcard * here denotes every vertex; for example, {f0,∗,L}\{f_{0,*,L}\} denotes the set of all f0,i,Lf_{0,i,L} as ii ranges over every vertex). The official solution2 proves that the shortest bad string, if one exists, has length at most n1+n2n_1+n_2, so the complexity of this method is reliable.

Next consider the specific hash method. The usual method—mapping a string a1a2⋯aka_1a_2\cdots a_k to (a1+Pa2+P2a3+⋯+Pk−1ak) mod Q\big(a_1+Pa_2+P^2a_3+\cdots+P^{k-1}a_k\big)\bmod Q, and defining the hash of a multiset as the sum of the hashes of its elements modulo QQ—does not work here. For example, the sets {"ab","cd"} and {"cb","ad"} have the same hash value regardless of how P,QP,Q are chosen.

The problem with the method above is that the hash value of a string is a sum, so its terms can be separated and rearranged. To avoid this problem, we consider changing the hash value into a product. In addition, the commutativity of multiplication makes different positions indistinguishable, so we assign different weights to different positions to avoid this.

For every pair (c,j)(c,j), where cc is a character and jj is an integer indicating the position of cc in a string, we pre-generate a random number xc,jx_{c,j}. We map a string a1a2⋯aka_1a_2\cdots a_k to xa1,1xa2,2⋯xak,k mod Qx_{a_1,1}x_{a_2,2}\cdots x_{a_k,k}\bmod Q, where QQ is a randomly chosen prime, and define the hash of a multiset as the sum of the hashes of its elements modulo QQ. We now analyze the error rate.

(*)Schwartz–Zippel lemma

Let f∈F[z1,⋯ ,zk]f\in F[z_1,\cdots,z_k] be a nonzero polynomial over a field FF in kk variables of degree dd, and let SS be a finite subset of FF. Then at most d⋅∣S∣k−1d\cdot |S|^{k-1} tuples (z1,⋯ ,zk)∈Sk(z_1,\cdots,z_k)\in S^k satisfy f(z1,⋯ ,zk)=0f(z_1,\cdots,z_k)=0.

If you do not know what a field is

You only need to remember that both of the following are fields:

  1. The residue classes modulo a prime, together with their operations.
  2. The set of real numbers, together with their operations.

Corollary: if z1,⋯ ,zkz_1,\cdots,z_k are independently selected uniformly from SS, then Pr[f(z1,⋯ ,zk)=0]≤d∣S∣\mathrm{Pr}\big[f(z_1,\cdots,z_k)=0\big]\leq \dfrac d{|S|}.

Let FF be the field corresponding to the residue classes modulo QQ. For an L≤n1+n2L\leq n_1+n_2, ∑if0,i,L\sum\limits_i f_{0,i,L} and ∑if1,i,L\sum\limits_i f_{1,i,L} correspond respectively to polynomials over FF in the variable set {x∗,∗}\{x_{*,*}\} of degree LL. Denote these two polynomials by P0,P1P_0,P_1.

If two different string multisets have the same hash value, there are two possibilities:

  1. P0≡P1(modQ)P_0\equiv P_1\pmod {Q}; that is, the coefficients of every term of P0,P1P_0,P_1 are equal modulo QQ.
  2. P0≢P1(modQ),P0(x∗,∗)≡P1(x∗,∗)(modQ)P_0\not\equiv P_1\pmod {Q}, P_0(x_{*,*})\equiv P_1(x_{*,*})\pmod {Q}; that is, P0,P1P_0,P_1 are not identically equal, but the selected {x∗,∗}\{x_{*,*}\} happen to make their values at this point equal.

Analyze the probability of the first case:

  • Observation: for any A≠B;A,B≤NA\neq B; A,B\leq N and a randomly selected prime Q≤Qmax⁡Q\leq Q_{\max}, we have:
Pr[A≡B(modQ)]=O(log⁡Nlog⁡QmaxQmax)\mathrm{Pr}\big[A\equiv B\pmod {Q}\big]=O\Big(\dfrac{\log N \log Q_{max}}{Q_{max}}\Big)
  • This is because A≡BA\equiv B can hold only when QQ satisfies Q∣(A−B)Q\big|(A-B), and such QQ are counted by ω(A−B)≤log⁡2N\omega(A-B)\leq \log_2 N. By the prime number theorem, the number of distinct primes no greater than Qmax⁡Q_{\max} is Θ(Qmax⁡log⁡Qmax⁡)\Theta\Big(\dfrac {Q_{\max}}{\log Q_{\max}}\Big). Dividing the former count by the latter gives the formula above.
  • In the observation above, take A,BA,B with A≠BA\neq B to be the coefficients of a particular term in P0,P1P_0,P_1 (which are also the occurrence counts of the corresponding string in G0,G1G_0,G_1). Clearly A,B≤(m1+m2)LA,B\leq (m_1+m_2)^{L}, so we obtain:
Pr[A≡B(modQ)]=O(Llog⁡(m1+m2)log⁡QmaxQmax)\mathrm{Pr}\big[A\equiv B\pmod {Q}\big]=O\Big(\dfrac{L\log (m_1+m_2) \log Q_{max}}{Q_{max}}\Big)
  • Therefore, taking Qmax⁡≈1012Q_{\max}\approx 10^{12} is more than sufficient. If the machine cannot support integer operations on numbers this large, double hashing can be used instead.

Analyze the probability of the second case:

  • In the Schwartz–Zippel lemma:
    • take the field FF corresponding to the residue classes modulo QQ;
    • take f(x∗,∗)=P0(x∗,∗)−P1(x∗,∗)f(x_{*,*})=P_0(x_{*,*})-P_1(x_{*,*}) to be a nonzero degree-LL polynomial;
    • take S=FS=F.
  • We obtain that the desired probability is ≤LQ\leq \dfrac LQ.

Notice that we need to guarantee correctness for every LL, so for a rigorous argument we also need to use the Union Bound (see below) to explain this.

In practice, we do not need to choose the modulus randomly because—for example—using our birthday as the modulus is already equivalent to using a random number.

Example: (*) number of distinct elements in a submatrix

Problem

Given an n×mn\times m matrix, answer qq queries for the number of distinct elements in a contiguous submatrix, using an online algorithm.

An error tolerance of ϵ\epsilon and an error rate of δ\delta are allowed; in other words, for at least (1−δ)q(1-\delta)q queries, your answers must have relative error from the correct answer no greater than ϵ\epsilon.

n⋅m≤2⋅105;q≤106;ϵ=0.5,δ=0.2n\cdot m\leq 2\cdot10^5;q\leq 10^6;\epsilon=0.5,\delta=0.2

Lemma: let X1⋯kX_{1\cdots k} be mutually independent random variables uniformly distributed in [0,1][0,1]. Then E[min⁡iXi]=1k+1\mathrm{E}\big[\min\limits_i X_i\big]=\dfrac 1{k+1}.

  • Proof: consider a unit circle with k+1k+1 points distributed uniformly at random by relative position, at positions 0,X1,X2,⋯ ,Xk0,X_1,X_2,\cdots,X_k. Then min⁡iXi\min\limits_i X_i is the length of one particular segment among the k+1k+1 gaps. Since these gaps are “symmetric”, the expected length of any particular gap is 1k+1\dfrac 1{k+1}.

Take kk to be the number of distinct elements and use the lemma above to infer, from min⁡iXi\min\limits_i X_i, the number kk.

Consider a hash function that maps every matrix element independently and uniformly to a real number in [0,1][0,1], with equal elements mapped to equal real numbers. Then the real numbers corresponding to all elements of a submatrix, after deduplication, form an instance of the preceding set {X1,⋯ ,Xk}\{X_1,\cdots,X_k\}, where kk equals the number of distinct elements in the submatrix.

Thus we obtain the algorithm:

  1. Assign a hash value in [0,1][0,1] to every matrix element. To ensure randomness, the hash function can be implemented directly with map and a random-number generator: whenever a new value is encountered, assign it a random hash value.
  2. When answering a query, find the minimum hash value MM in the submatrix and output 1M−1\dfrac 1M-1.

However, this algorithm is not satisfactory. Its output has expectation E[1min⁡iXi−1]\mathrm{E}\Big[\dfrac 1{\min\limits_i X_i}-1\Big], but in fact this is not equal to 1E[min⁡iXi]−1=k\dfrac 1{\mathrm{E}\big[\min\limits_i X_i\big]}-1=k; it is instead (as can be proved) equal to ∞\infty.

In other words, we cannot put a single value of min⁡iXi\min\limits_i X_i directly in the denominator. We must first compute its expectation and then put the expected value in the denominator.

How do we compute the expected value? Take the average of multiple random samples.

Use CC different hash functions to perform the preceding process separately. When answering a query, compute CC different values of MM, take their average M‾\overline M, and output (M‾)−1−1\big(\overline M\big)^{-1}-1.

Experiments show that taking C≈80C\approx 80 is sufficient. A rigorous proof is very tedious and is omitted here.

Finally, how do we find the minimum of a submatrix? Use a two-dimensional S-T table: preprocess in O(nmlog⁡nlog⁡m)O(nm\log n\log m) time and answer each query in O(1)O(1).

Other applications of randomization in algorithms

Other uses of randomization include:

  • Preventing the data setter from defeating the algorithm with targeted data, for example by randomly shuffling the order of neighbors during a search.
  • Ensuring that the operations performed during the algorithm are uniform in some sense, for example in the simulated annealing algorithm.

In these situations, randomization is often, though not always, associated with ad hoc methods and attempts to obtain points.

Example: TJOI2015 Linear Algebra

The standard algorithm for this problem is network flow, but here we use the following ad hoc method:

  • Randomly choose a position each time, flip the value at that position, check the value, and update the answer.
Code
#include <algorithm>
#include <cstdlib>
#include <iostream>

int n;

int a[510], b[510], c[510][510], d[510];
int p[510], q[510];

int maxans = 0;

void check() {
  memset(d, 0, sizeof d);
  int nowans = 0;
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= n; j++) d[i] += a[j] * c[i][j];
  for (int i = 1; i <= n; i++) nowans += (d[i] - b[i]) * a[i];
  maxans = std::max(maxans, nowans);
}

int main() {
  srand(19260817);
  std::cin >> n;
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= n; j++) std::cin >> c[i][j];
  for (int i = 1; i <= n; i++) std::cin >> b[i];
  for (int i = 1; i <= n; i++) a[i] = 1;
  check();
  for (int T = 1000; T; T--) {
    int tmp = rand() % n + 1;
    a[tmp] ^= 1;
    check();
  }
  std::cout << maxans << '\n';
}

Example: (*) randomized heap3

The most common way to implement a mergeable heap is probably a leftist tree, which maintains the tree height and keeps the tree left-biased to guarantee merge complexity. However, maintaining the height is somewhat cumbersome, so we would like to avoid it as much as possible.

Thus we can consider using a randomized heap, which swaps children randomly instead of comparing their heights.

Code
struct Node {
  int child[2];
  long long val;
} nd[100010];

int root[100010];

int merge(int u, int v) {
  if (!(u && v)) return u | v;
  int x = rand() & 1, p = nd[u].val > nd[v].val ? u : v;
  nd[p].child[x] = merge(nd[p].child[x], u + v - p);
  return p;
}

void pop(int &now) { now = merge(nd[now].child[0], nd[now].child[1]); }

A randomized heap has no hard or soft requirements on its shape, and the expected complexity of merging any two heaps, as arguments to the merge function, satisfies the same bound. We prove this below.

Proof of the expected complexity

We prove that, for any heap AA, starting from the root and randomly choosing left or right at each step until no further step is possible, the expected path length (that is, the number of vertices on the path) satisfies h(A)≤log⁡2(∣A∣+1)h(A)\leq\log_2 (|A|+1).

  • Notice that the expected complexity of merging heaps A,BA,B in the preceding process is O(h(A)+h(B))O\big(h(A)+h(B)\big), so the conclusion above guarantees the expected complexity of a randomized heap.

We use mathematical induction. The base case is the empty heap AA, for which the claim is obvious. Assume AA is nonempty.

Suppose the two subtrees of AA are L,RL,R. Then:

h(A)=1+h(L)+h(R)2≤1+log⁡2(∣L∣+1)+log⁡2(∣R∣+1)2=log⁡22(∣L∣+1)(∣R∣+1)≤log⁡22((∣L∣+1)+(∣R∣+1))2=log⁡2(∣A∣+1)\begin{align} h(A) &=1+\frac{h(L)+h(R)}2 \\&\leq1+\frac{\log_2(|L|+1)+\log_2(|R|+1)}2 \\&=\log_2{2\sqrt{(|L|+1)(|R|+1)}} \\&\leq\log_2{\frac{2\big((|L|+1)+(|R|+1)\big)}2} \\&=\log_2{(|A|+1)} \end{align}

This proves the claim.

Proof techniques involving randomness

The following are several useful techniques.

Naturally, these few items cannot be exhaustive. If you know of a technique that is not listed, please feel free to add it.

Analysis of probability bounds

See the page on probability inequalities for details.

In addition to the inequalities mentioned on that page, the following conclusion is also frequently used in derivations:

Using the natural constant: (1−1n)n≤1e,∀n≥1\Big(1-\dfrac{1}{n}\Big)^n\leq \dfrac{1}{\mathrm{e}},\forall n\geq1

  • The left-hand side is monotonically increasing with respect to n≥1n\geq 1 and its limit at +∞+\infty is 1e\dfrac{1}{\mathrm{e}}, which proves the conclusion.
  • This tells us that if nn mutually independent events each occur with probability 1−1n1-\dfrac 1n, then the probability that they all occur is at most 1e\dfrac{1}{\mathrm{e}}.

The coupling idea

The coupling idea is often used to handle more than one random object at the same time, or to handle a random object and a deterministic object simultaneously.

Prelude: connectivity of random graphs

Problem

For n∈N∗;p,q∈[0,1]n \in \mathbf{N}^*; p,q\in [0,1] with q≤pq\leq p, prove that the expected number of connected components of the random graph G1(n,p)G_1(n,p) is no greater than the expected number of connected components of the random graph G2(n,q)G_2(n,q). Here G(n,α)G(n,\alpha) denotes a simple undirected graph with nn vertices, denoted GG, in which each of the n(n−1)2\dfrac {n(n-1)}2 possible edges appears independently with probability α\alpha.

This conclusion looks completely natural, but a rigorous proof is not quite so easy.

Proof idea

Imagine that the two graphs use separate 01 random number generators to determine whether each edge exists. The generator for G1G_1, denoted T1T_1, outputs 1 with probability pp, while the generator for G2G_2, denoted T2T_2, outputs 1 with probability qq. Thus, constructing a graph only requires running the corresponding generator n(n−1)2\dfrac {n(n-1)}2 times.

Now combine the two generators into one. Consider a random number generator TT that outputs 0 with probability qq, 1 with probability p−qp-q, and 2 with probability 1−p1-p. If we run TT n(n−1)2\dfrac {n(n-1)}2 times, we can construct G1G_1 and G2G_2 simultaneously. Specifically, if the output is 0, regard the currently considered edge as absent from both G1G_1 and G2G_2; if it is 1, regard it as present only in G1G_1; if it is 2, regard it as present in both G1G_1 and G2G_2.

It is easy to verify that the resulting G1G_1 and G2G_2 satisfy their definitions, and that in every instance the edge set of G2G_2 is a subset of the edge set of G1G_1. Therefore, in every instance, G2G_2 has at least as many connected components as G1G_1, so the same inequality naturally holds for their expectations.

The idea used in this proof is called “coupling”, which can be understood from its literal meaning. Here it consists of combining two originally independent random processes into one.

Application: NERC 2019 Problem G: Game Relics

Brief problem statement

There are several items, each with a price cic_i. You want to obtain all items, and may perform either of the following operations:

  1. Choose an item ii that you do not own and buy it for cic_i.
  2. Pay xx to draw one item uniformly at random from all items, including those already owned. If you do not yet own the item, acquire it directly; otherwise, acquire nothing but receive a refund of x2\dfrac x2. Here xx is an input constant.

What is the expected cost under the optimal strategy?

Observation: if we choose to draw items, we will certainly keep drawing until we obtain a new item.

  • Reason: if a draw does not produce a new item, the state is exactly the same as before the draw. Therefore, if the optimal action in the old state is to draw once, the optimal action in the new state must also be to draw once more.

We can define fkf_k as the expected amount of money needed to draw a new item when we currently own kk different items. By the observation above, we can treat fkf_k directly as a fixed cost, turning the process into one in which we pay fkf_k each time to obtain a new item at random.

Computing the expected cost

Clearly fk=x2⋅(R−1)+xf_k=\dfrac x2 \cdot (R-1)+x, where RR is the expected number of draws needed to obtain a new item.

Lemma: if a coin lands heads with probability pp, the expected number of tosses until the first head is 1p\dfrac 1p.

  • Intuitively, 1p⋅p=1\dfrac 1p \cdot p = 1, so tossing this many times is expected to produce one head, which seems reasonable.
  • This intuition can be made rigorous using the law of large numbers, by considering n→∞n\to \infty experiments of “repeatedly toss a coin until obtaining heads.” Details are omitted.
  • Another possible proof is to substitute directly into the definition of expectation and calculate it by brute force. Details are omitted.

Clearly, the probability of obtaining a new item on one draw is n−kn\dfrac {n-k}n, so R=nn−kR=\dfrac n{n-k}.

Conclusion: the optimal strategy is always to draw several times first and then buy all items that were not drawn.

This conclusion agrees with intuition, because fkf_k increases with kk, so drawing early does indeed seem somewhat better than drawing late.

Proof

First consider a special case. We prove:

  • Random process AA: first buy item xx, then keep drawing until all items are obtained.
  • ……never better than……
  • Random process BB: keep drawing until all items other than xx are obtained, then buy xx if it has not yet been obtained.

Let random processes AA and BB use the same random number generator. That is, the first draw of AA and the first draw of BB produce the same element, and the second, third, and later draws are also the same.

Clearly, AA and BB must make the same number of draws. For an item drawn by process AA, namely y≠xy\neq x, observe that:

  • The number of items already owned by AA when it draws yy is always at least the number already owned by BB when it draws yy.

Therefore, the cost of each draw in BB is no greater than that in AA, and hence the total drawing cost is no greater than AA's.

Clearly, BB's purchase cost is also no greater than AA's. Therefore, BB is never worse than AA.

We can then generalize this conclusion to the general case by mathematical induction. Specifically, each time we find the last purchase in the current strategy, we move this purchase to the end using the conclusion above, which is never worse. Details are omitted.

Based on this conclusion, we can equivalently transform the problem again: replace the operation “choose an item and buy it for its price” with “randomly choose an item not yet owned and buy it for its price”. The operations are equivalent because, if buying is only used to clean up at the end, it does not matter which item is chosen.

We now see that drawing and buying have effectively become the same operation; the only difference is the price paid. Choosing to buy or draw has no effect on the order in which items are obtained, and every order of obtaining the items is equally likely.

Observation: at a given moment, we should choose to buy if and only if the cost of the next draw, determined by the number of items already drawn, is greater than the average price of the remaining items; if they are equal, either choice is acceptable.

  • It can be proved that, over time, the draw cost increases no more slowly than the average price of the remaining items. This shows that there is only one “threshold point” at which we switch from drawing to buying, further confirming the previous conclusion.

Finally, enumerate all possible states, that is, the sets of items already owned. Calculate the probability of reaching each state, given by the number of permutations of the owned items divided by the total number of permutations, multiply it by the cost of the optimal decision in the current state, determined by the number of owned items and the total price of the remaining items, and add everything together. This process can be optimized with knapsack-style DP, which solves the problem.


Review: The coupling technique is used twice in this problem. The first time is in the proof, where the two random processes use the same random source. The second time is in transforming buying into random buying, that is, introducing a random source so that buying and drawing become essentially the same operation by having them share a random source.

References

Footnotes

  1. PANIC - Editorial ↩

  2. UOJ NOI Round #4 Day2 Solution ↩

  3. Anna Gambin and Adam Malinowski, Randomized Meldable Priority Queues ↩

This content comes from OI Wiki: Randomization Techniques. See the original for authors and revision history. AIOJ has adapted the formatting, in-site links, and resource paths.

Content is shared under CC BY-SA 4.0 and SATA license; additional terms are governed by the original notice. Thanks to the OI Wiki authors and contributors; per the SATA terms, please visit the OI Wiki repository and star it to show your support.