Educational Round #7 — Editorial
There are ways to choose distinct integers from .
Let us consider how many subsets of numbers have the minimum element equal to . For this, the subset must include the number , and additionally choose numbers, each of which is strictly greater than . There are numbers greater than , and the number of ways to choose numbers from them is .
Note that the inequality must hold; otherwise, it is impossible to choose numbers greater than . This leads to the constraint .
To compute the expected value of the , we need to find the weighted average of this value over all possible subsets:
If , then the number of corresponding subsets is considered to be zero.
Example
In the first test case, there is only one possible selection: . The minimum element is , so the required value is .
In the second test case, there are three equally likely selections: , and . The corresponding values of are , and . Therefore, the average value of the is
Now compute the required answer using the formula:
The function Cnk computes the value of the binomial coefficient . The values of the binomial coefficients will be stored in the cells of the array .
long long dp[51][51];
long long Cnk(int n, int k)
{
if (n == k) return 1;
if (k == 0) return 1;
if (dp[n][k] != -1) return dp[n][k];
return dp[n][k] = Cnk(n - 1, k - 1) + Cnk(n - 1, k);
}The main part of the program.
scanf("%d %d", &n, &x);
memset(dp, -1, sizeof(dp));Compute the answer: .
a = 0; for (i = 1; i <= n - x + 1; i++) a = a + Cnk(n - i, x - 1) * (1LL << i); res = 1.0 * a / Cnk(n, x);
Print the answer.
printf("%lf\n", res);A directed graph with vertices and edges is given, with vertices numbered from to . Find the minimum number of edges that need to be reversed so that there exists at least one path from vertex to vertex .
Input. The first line contains two integers and — the number of vertices and edges in the graph. Each of the following lines contains two integers and , indicating that the -th directed edge goes from vertex to vertex .
Output. Print the minimum number of edges that need to be reversed. If it is not possible to obtain a path from vertex to vertex , print .

7 7 1 2 3 2 3 4 7 4 6 2 5 6 7 5
2
Сonstruct a graph by assigning a weight of to the existing edges and a weight of to their reversed edges. Then, run a breadth-first search. The length of the shortest path from vertex to vertex will equal the minimum number of edges that need to be reversed.
Example
The graph in the example looks as follows:
Declare the constant infinity.
#define INF 0x3F3F3F3F
Declare the array of shortest distances and the adjacency list of the graph . For each edge, store its weight ( or ) along with the adjacent vertex.
vector<int> dist; vector<vector<pair<int, int> > > g;
The bfs function implements breadth-first search from the vertex .
void bfs(int start)
{
dist = vector<int>(n + 1, INF);
dist[start] = 0;
deque<int> q;
q.push_back(start);
while (!q.empty())
{
int v = q.front(); q.pop_front();
for (auto edge : g[v])
{
int to = edge.first;
int w = edge.second;
if (dist[to] > dist[v] + w)
{
dist[to] = dist[v] + w;Depending on the weight of the edge , add vertex to the end or the front of the queue.
if (w == 1)
q.push_back(to);
else
q.push_front(to);
}
}
}
}The main part of the program. Read the input data.
scanf("%d %d", &n, &m);
g.resize(n + 1);
for (i = 0; i < m; i++)
{
scanf("%d %d", &a, &b);Assign a weight of to a directed edge , and a weight of to the reverse edge.
g[a].push_back({ b, 0 });
g[b].push_back({ a, 1 });
}Start the breadth-first search from the vertex .
bfs(1);
Print the answer — the shortest distance to vertex .
if (dist[n] == INF)
printf("-1\n");
else
printf("%d\n", dist[n]);The transportation system of the city of Baku consists of intersections and bidirectional roads connecting them. Each road connects exactly two intersections, and there can be at most one road between any pair of intersections. Moreover, it is possible to travel between any two intersections using the existing roads.
The distance between two intersections is defined as the minimum number of roads among all possible paths connecting them.

The city mayor has decided to improve the transportation system and has instructed the director of the transportation department to build a new road. However, the mayor recently bought a new car and enjoys driving from home to work and back every day. He does not want the distance between intersection , where his home is located, and intersection , where his workplace is located, to decrease after the new road is built.
Help the director of the transportation department determine how many pairs of unconnected intersections exist such that if a road is built between them, the distance between and will not decrease.
Input. The first line contains four integers:
— the number of intersections,
— the number of roads,
— the intersection where the mayor's home is located,
— the intersection where the mayor's workplace is located.
The next lines each contain two integers and , indicating that there is a bidirectional road between intersections and .
Output. Print the number of pairs of unconnected intersections such that adding a road between them will not decrease the distance between intersections and .

5 4 1 5 1 2 2 3 3 4 4 5
0
5 4 3 5 1 2 2 3 3 4 4 5
5
Let's run a breadth-first search starting from the source vertex and the destination vertex . Store the shortest distances from in the array and from in the array .
Let denote the shortest distance between and in the original graph.
Now, let's consider the possibility of building a new road between vertices and .
When adding a road to the graph, new paths are created:
If at least one of these distances is smaller than , then adding the road will decrease the shortest distance between and , and thus it is not suitable.
We now need to check all possible pairs and verify if adding a new road will decrease the shortest distance between and .
Example
The graph from the first test is shown on the left. The shortest distance from vertex to vertex is . No matter which new road we add, this distance will decrease. Therefore, none of the required roads exist.
The graph from the second test is shown on the right. The shortest distance from vertex to vertex is . The possible new roads are marked with bold lines. Regardless of which of these roads we build, the distance between and will not decrease.
Define the constant — the maximum possible number of vertices in the graph.
#define MAX 1001
Declare the adjacency matrix and the arrays for the shortest distances.
int g[MAX][MAX], distS[MAX], distF[MAX];
The function bfs performs a breadth-first search from the vertex . It takes the array as input, where the shortest distances will be stored.
void bfs(int start, int *dist)
{Initialize the array of shortest distances .
for (int i = 0; i <= n; i++) dist[i] = -1; dist[start] = 0;
Declare a queue and add the starting vertex to it.
queue<int> q; q.push(start);
While the queue is not empty, dequeue the vertex .
while (!q.empty())
{
int v = q.front(); q.pop();Iterate through all vertices adjacent to . If vertex is not visited yet, compute the shortest distance and add it to the queue.
for (int to = 1; to <= n; to++)
if (g[v][to] && dist[to] == -1)
{
q.push(to);
dist[to] = dist[v] + 1;
}
}
}The main part of the program. Read the input data.
scanf("%d %d %d %d", &n, &m, &s, &f);
memset(g, 0, sizeof(g));Read the undirected graph.
for (i = 0; i < m; i++)
{
scanf("%d %d", &a, &b);
g[a][b] = g[b][a] = 1;
}Run a breadth-first search from vertices and . The shortest distances are stored in the arrays and , respectively.
bfs(s, distS); bfs(f, distF);
Let denote the shortest distance between and in the original graph.
optDistance = distS[f];
Iterate through all pairs of vertices and and consider the possibility of building a new road between them. The variable keeps track of the number of such valid roads.
res = 0; for (i = 1; i <= n; i++) for (j = i + 1; j <= n; j++)
If there is no road between vertices and , compute the lengths of the shortest paths: and . If both of these distances are not less than , then building such a road is allowed.
if (g[i][j] == 0)
{
if ((distS[i] + distF[j] + 1 >= optDistance) &&
(distS[j] + distF[i] + 1 >= optDistance))
res++;
}Print the answer.
printf("%d\n", res);Find the weight of the minimum spanning tree for an undirected weighted connected graph.
Input. The first line contains the number of vertices and the number of edges (, ). Each of the following lines contains three integers , , , where and are the vertex numbers connected by an edge, and is the weight of the edge (a positive integer not exceeding ).
Output. Print the weight of the minimum spanning tree.

3 3 1 2 1 2 3 2 3 1 3
3
The task is to find the weight of the minimum spanning tree using Kruskal's algorithm.
Example The graph given in the example has the following form:
Exercise 1
Find the minimum spanning tree and its weight for the following graph.
Exercise 2
Find the minimum spanning tree and its weight for the following graph.
Declare a structure for the graph edge (a pair of vertices and the edge weight). Declare a vector of edges .
struct Edge
{
int u, v, dist;
};
vector<Edge> e;Declare an array , that will be used in the disjoint-set data structure.
vector<int> parent;
The function Repr finds the representative of the set that contains vertex .
int Repr(int n)
{
while (n != parent[n]) n = parent[n];
return n;
}The function Union unites the sets containing elements and .
int Union(int x, int y)
{
x = Repr(x); y = Repr(y);
if (x == y) return 0;
parent[y] = x;
return 1;
}The function lt is a comparator for sorting the edges.
int lt(Edge a, Edge b)
{
return (a.dist < b.dist);
}The main part of the program. Initialize the array.
scanf("%d %d",&n,&m);
parent.resize(n + 1);
for (i = 1; i <= n; i++) parent[i] = i;Read the edges of the graph.
e.resize(m);
for (i = 0; i < m; i++)
scanf("%d %d %d", &e[i].u, &e[i].v, &e[i].dist);Sort the edges of the graph in increasing order of weights.
sort(e.begin(), e.end(), lt);
Run Kruskal's algorithm to construct the minimum spanning tree.
res = 0; for(i = 0; i < m; i++) if (Union(e[i].u,e[i].v)) res += e[i].dist;
Print the weight of the minimum spanning tree.
printf("%d\n",res);You need to cut a wooden stick into pieces. The most affordable company, The Analog Cutting Machinery, Inc. (ACM), charges money based on the length of the stick being cut. The procedure requires making only one cut at a time.
It is easy to see that different choices of the cutting order lead to different costs. For example, consider a stick of length meters that needs to be cut at , , and meters from one end. Consider a few options:
You could cut first at meters, then at meters, and finally at meters. This would result in a cost of , because the first piece was meters, the second meters, and the third meters.
In another option, if you first cut at meters, then at meters, and finally at meters, the cost would be , which is the better price.
Your boss trusts your computing skills to determine the minimal cost of cutting the given stick.
Input. The input consists of several test cases. The first line of each test case contains the length of the stick that needs to be cut. The next line contains the number of cuts to be made.
The following line contains positive integers , representing the positions for the cuts, given in strictly increasing order. A line with denotes the end of the input data.
Output. Print the minimal cost of cutting the stick in the exact format given in the example.

100 3 25 50 75 10 4 4 5 7 8 0
The minimum cutting is 200. The minimum cutting is 22.
Let the array contain the cutting points: . Add the start and end points: and .
Let the function return the minimal cost of cutting a stick from to considering the necessary cutting points within the segment. There are no cutting points within the segment , so . The solution to the problem will be the value of . Store the computed values of in the cells of the array .
Let the segment of the stick be cut into several pieces. If the first cut is made at point , the cost of the cut itself will be . Then, the remaining pieces need to be cut at the costs and , respectively. Choose to minimize the total cost:
Example
Consider the second test case. Here is one possible way to cut a stick of length with a cost of :
Now, consider the optimal way to cut the stick, which has a cost of :
Declare constants and arrays.
#define MAX 55 #define INF 0x3F3F3F3F int dp[MAX][MAX]; int m[MAX];
The function returns the minimum cost of cutting a piece of stick on the segment at the cutting points located inside the segment.
int f(int a, int b)
{If , then there are no cutting points within the segment . Return .
if (b - a == 1) return 0;
If the value of is already computed, return it.
if (dp[a][b] != INF) return dp[a][b];
Make a cut at the point . Compute the cost as follows:
for (int i = a + 1; i < b; i++)
dp[a][b] = min(dp[a][b], m[b] - m[a] + f(a, i) + f(i, b));Return the result .
return dp[a][b]; }
The main part of the program. Read the input data for each test case.
while(scanf("%d",&l),l)
{
scanf("%d",&n);Add the start and end cutting points: .
m[0] = 0; m[n+1] = l;
for(i = 1; i <= n; i++)
scanf("%d",&m[i]);Initialize the array.
memset(dp,0x3F,sizeof(dp));
Find and print the answer.
printf("The minimum cutting is %d.\n",f(0,n+1));
}Near Pemberley Villa, located in the southern district of Byteland, there is a large pasture. Mrs. Darcy is concerned about her delicate plants, which could be trampled by strangers. Therefore, she decided to enclose certain areas of the pasture with triangular fences.
In Mrs. Darcy's basement, there are several fences. She forms each triangular area using exactly three fences, so that each side of the triangle corresponds to one fence. The fences are sturdy and beautiful, so she will not combine multiple fences to form a single side, nor will she cut a fence into shorter pieces. Mrs. Darcy's goal is to enclose the largest possible total area of the pasture.
Input. Each line contains a separate test case. The first number in the line is the number of fences that Mrs. Darcy has. The next integers, each between and , are the lengths of these fences.
Output. For each test case, print in a separate line the maximum area that can be enclosed using the available fences. The answer must be printed with decimal digits.
Examples. In the first test case, it is optimal to construct triangles with sides and . The total enclosed area in this case is .
In the second test case, the answer is , since it is impossible to form any triangle.
In the third test case, a triangle with sides should be built. Note that fence lengths can repeat.
7 3 4 5 6 7 8 9 4 1 2 4 8 4 7 4 4 4
36.7544 0.0000 6.9282
The area of a triangle with sides and is computed in the function area using Heron's formula:
Let be some subset of the available fence pieces. The function FindSol() finds the maximum area that can be enclosed using triangles formed from the pieces in this subset.
The variable represents a subset mask: it is a -bit number whose -th bit is equal to if the subset contains the piece , and otherwise.
The answer to the problem is the value FindSol(, where is the number of elements in the array .
The values of all possible masks lie in the range from to (since, according to the constraints, there are no more than fence pieces). The array entry stores the maximum area that can be enclosed by the subset of fence pieces corresponding to the mask .
To compute FindSol() all possible triples of fence pieces that are present in should be enumerated. For each triple, the triangle inequality is checked to ensure that a triangle can be formed from these pieces. If a triangle is possible, the following sum is computed:
Next, all such triples are considered, and the one for which this sum is maximal is selected. This maximum value is assigned to :
If the lengths of the fence pieces are initially sorted, then when checking the triangle inequality (for a triangle with sides ), it is sufficient to check only one condition:
Since after sorting we have
it always follows that
Example
In the first test, the optimal triangles to construct have sides and . The total enclosed area in this case is .
In the second test, the answer is , since no triangle can be formed from the available fences.
In the third test, a triangle with sides should be constructed. Note that fence lengths can be repeated.
Declare the global variables.
#define MAX 16 double best[1<<MAX]; int f[MAX+1];
The function area computes the area of a triangle using Heron's formula.
double area(int a, int b, int c)
{
double p = (a + b + c) / 2.0;
return sqrt(p * (p - a) * (p - b) * (p - c));
}The function FindSol returns the maximum area that can be enclosed using triangles formed from the fences included in the mask .
double FindSol(int mask)
{If the value in the array is greater than or equal to zero, it has already been computed, and the function returns this value. This avoids redundant computations and speeds up the algorithm.
if (best[mask] >= 0.0) return best[mask];
Initialize .
best[mask] = 0;
Iterate over all possible triples of indices such that the corresponding fences are included in .
for (int i = 0; i < n - 2; i++) if (mask & (1 << i)) for (int j = i + 1; j < n - 1; j++) if (mask & (1 << j)) for (int k = j + 1; k < n; k++) if (mask & (1 << k))
Check the triangle existence condition. Since the fences are initially sorted, this condition is sufficient to ensure that a triangle can be formed.
if (f[i] + f[j] > f[k])
If the triangle exists, compute the sum:
the area of the current triangle ;
plus the maximum area that can be enclosed with the remaining fences, excluding those used in this triple:
best[mask] = max(best[mask], area(f[i],f[j],f[k]) +
FindSol(mask ^ (1 << i) ^ (1 << j) ^ (1 << k)));
return best[mask];
}The main part of the program. Read the number of fences .
while (scanf("%d",&n) == 1)
{
memset(f,0,sizeof(f));Read the lengths of the fences and sort them in non-decreasing order.
for (i = 0; i < n; i++) scanf("%d",&f[i]);
sort(f,f + n); Initialize the array .
for (i = 0; i < (1 << MAX); i++) best[i] = -1.0;
Compute and print the answer.
printf("%.4lf\n",FindSol((1 << n) - 1));
}Vasya received a rectangular matrix of size as a gift from his mother. Each cell of the matrix contains an integer. At first, Vasya enthusiastically played various mathematical games with the matrix: sometimes he would swiftly compute its determinant, and sometimes he would easily raise it to different powers.
However, he eventually got bored of such games and came up with a new pastime: Vasya chooses an integer and tries to find a submatrix of maximum area such that the sum of all its elements does not exceed . A submatrix is defined as a rectangular fragment of the original matrix.
Input. The first line contains three integers: , , and .
The next lines each contain non-negative integers, each of which does not exceed .
Output. Print a single integer — the area of the largest submatrix whose sum of elements does not exceed .
1 3 4 8 6 4
1
3 3 12 7 5 7 8 4 8 4 3 2
3
Let be the input rectangular matrix. Create a two-dimensional array of the same size, where represents the sum of elements in the submatrix with opposite corners at points and . The values in this array can be computed using the following formula:
Now consider a submatrix of array of size . Let its opposite corners be located at coordinates and .
Then the sum of all elements in the submatrix is calculated using the formula:
Let's solve the problem using brute-force search. Iterate over all possible submatrix sizes , as well as all valid coordinates of the top-left corner of the submatrix. Using the array, compute the sum of elements inside the current submatrix in constant time. If this sum does not exceed , we keep track of the maximum area among all such submatrices.
However, this brute-force approach has a time complexity of , which is too slow. We can speed it up to by applying binary search on the width of the submatrix.
Fix the top-left corner . Let denote the sum of elements in the submatrix with corners at and . If we fix the height and treat the width as a variable, then becomes a non-decreasing function with respect to , since the original matrix contains non-negative integers. This allows us to use binary search to find the maximum value of for which .
Example
For example, the sum of the numbers in the submatrix with corners at points and is
The input matrix is stored in the array .
#define MAX 210 int a[MAX][MAX], dp[MAX][MAX];
The function returns if there exists a submatrix of size such that the sum of its elements does not exceed . To check this, all possible coordinates of the top-left corner are iterated over, and the sum of elements in the rectangle with corners at and is computed in constant time using the array.
int f(int w, int h)
{
for (int i = 1; i + w - 1 <= n; i ++)
for (int j = 1; j + h - 1 <= m; j ++)
if (dp[i + w - 1][j + h - 1] - dp[i + w - 1][j - 1] –
dp[i - 1][j + h - 1] + dp[i - 1][j - 1] <= k) return 1;
return 0;
};The main part of the program. Read the input matrix.
scanf("%d %d %d",&n,&m,&k);
for (i = 1; i <= n; i++)
for (j = 1; j <= m; j++)
scanf("%d",&a[i][j]);Based on the input matrix , compute the auxiliary matrix .
for (i = 1; i <= n; i++) for (j = 1; j <= m; j++) dp[i][j] = dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1] + a[i][j];
Iterate over the possible values of the submatrix width .
answer = 0;
for (w = 1; w <= n; w++)
{The length of the submatrix is determined using binary search over the range .
l = 1; r = m;
while (l < r)
{
mid = (l + r) / 2;For a submatrix of size , iterate over all possible positions of its top-left corner . If there exists at least one position where the sum of elements in the submatrix does not exceed , update the value of the resulting area .
if (f(w,mid))
{
answer = max(answer, w * mid);
l = mid + 1;
}
else r = mid;
}
mid = (l + r) / 2;
if (f(w,mid))
answer = max(answer, w * mid);
};Print the area of the largest submatrix found.
printf("%d\n",answer);