Educational Round #1 — Editorial
Let be the sides of a triangle. A triangle is right-angled if one of the following conditions holds:
(the hypotenuse is side )
(the hypotenuse is side )
(the hypotenuse is side )
Read the input data until the end of the file.
while(scanf("%d %d %d",&a,&b,&c)) {
If three zeros are encountered, terminate the program.
if (a + b + c == 0) break;
Check whether the triangle is a right triangle. Print the result accordingly.
if ((a * a + b * b == c * c) || (a * a + c * c == b * b) || (b * b + c * c == a * a)) puts("right"); else puts("wrong"); }
Hogwarts is hosting its traditional annual Magic Theory Olympiad for first-year students. The school's caretaker, Argus Filch, has been tasked with assigning students to classrooms.
Each of the four houses has sent its best students to the Olympiad: students from Gryffindor, from Slytherin, from Hufflepuff, and from Ravenclaw. Filch has classrooms at his disposal.
Each classroom is enchanted with an expansion charm, so it can accommodate any number of students. However, it must be taken into account that students from the same house, when placed in the same room, might take the opportunity to cheat by sharing ideas on how to solve the tasks. Therefore, the number of students from the same house in any single classroom should be minimized.
We define an optimal seating arrangement as one that minimizes the maximum number of students from the same house in any classroom.
Determine the minimum possible number of students from the same house that Filch will have to place in the same classroom, even under an optimal seating arrangement.
Input. The first line contains four integers and — the number of students representing Gryffindor, Slytherin, Hufflepuff, and Ravenclaw, respectively.
The second line contains a single integer — the number of available classrooms.
Output. Print a single integer — the minimum possible number of students from the same house that will have to be placed in the same classroom, even with an optimal arrangement.
4 3 4 4 2
2
15 14 13 14 5
3
The largest faculty has students. If we try to distribute them evenly across classrooms, then at least one of the classrooms will have no fewer than students. This is the minimum number of students from a single faculty that will have to be seated in one classroom, even with an optimal arrangement.
Read the input data.
scanf("%d %d %d %d", &g, &s, &h, &r); scanf("%d", &m);
Compute .
mx = g; if (s > mx) mx = s; if (h > mx) mx = h; if (r > mx) mx = r;
Let’s determine the maximum number of students that may end up in a single classroom: .
res = mx / m; if (mx % m > 0) res++;
Print the answer.
printf("%d\n", res);
A four-digit number is called an Armstrong number if the sum of the fourth powers of its digits equals the number itself.
For example: , therefore, is an Armstrong number.
Print all Armstrong numbers in the range from to .
Input. Two integers and .
Output. Print all Armstrong numbers in a single line in the range from to .
1000 3000
1634
Let's iterate through the numbers from to . For each number extract the digits of thousands , hundreds , tens , and ones . If the number is an Armstrong number , print it.
Read the input data.
scanf("%d %d", &a, &b);
Iterate through the numbers from to .
for (i = a; i <= b; i++) {
Extract the digits of the number .
x = a / 1000; y = i / 100 % 10; z = i / 10 % 10; u = i % 10;
If the number is an Armstrong number , print it.
if (x * x * x * x + y * y * y * y + z * z * z * z + u * u * u * u == i) printf("%d ", i); } printf("\n");
Divide the numbers into two groups so that the absolute difference between the sums of the elements in these groups is the smallest possible.
Input. One integer .
Output. In the first line, print two integers — the number of elements in the first and second groups.
In the second line, print the elements of the first group, and in the third line — the elements of the second group.
The elements within each group can be printed in any order. Each number from to must be included in exactly one of the groups.
4
2 2 1 4 2 3
5
3 2 1 2 4 3 5
Note that if the numbers and are placed in one group, and and are placed in the other (so that the sum of numbers in each group is equal), the problem reduces to a similar problem of smaller size, namely, dividing the numbers into two groups.
For , the numbers are divided into groups as follows:
If three numbers remain, they can be divided into two groups: and .
If two numbers remain, they can be divided into groups: и . The difference between the sums of the groups will be .
If one number remains, it can be placed in either group. The difference between the sums of the groups will be .
If the sum of all numbers from to is even, they can be divided into two groups with equal sums.
If the sum of all numbers from to is odd, they can be divided into two groups with a sum difference of .
Example
Let . The numbers are placed into groups as follows:
Let . The numbers are placed into groups as follows:
Read the input value .
scanf("%d", &n);
Initialize the initial sums of the numbers in the groups, and to .
s1 = s2 = 0;
Iterate through the numbers from down to .
for (i = n; i > 0; i--)
If , place the number into the first group. Otherwise, place the number into the second group.
if (s1 < s2) { s1 += i; a.push_back(i); } else { s2 += i; b.push_back(i); }
Print the sizes of the groups.
printf("%d %d\n", a.size(), b.size());
Print the numbers of the first group.
for (i = 0; i < a.size(); i++) printf("%d ", a[i]); printf("\n");
Print the numbers of the second group.
for (i = 0; i < b.size(); i++) printf("%d ", b[i]); printf("\n");
Define an infinite sequence as follows:
Given the values and , compute .
Input. Five integers .
Output. Print the value of .
12 2 3 1 0
8
10000000 2 3 10000000 10000000
2
Since , storing all values is impossible, either using an array or a map structure due to memory limitations. Therefore, we’ll use recursion defined by the recurrence relation for computations.
At the same time, the values for will be stored in the array to avoid repeated computations and speed up the program.
To store the values , declare an array .
#define MAX 5000000 long long m[MAX];
The function f computes the value of .
long long f(long long n, long long p, long long q, long long x, long long y) {
If , then .
if (n <= 0) return 1;
If and the value is already computed (is not zero), return it.
if ((n < MAX) && m[n]) return m[n];
Perform a recursive computation of according to the formula provided in the problem statement.
long long temp = f(n/p-x,p,q,x,y) + f(n/q-y,p,q,x,y);
If , store the result in the array to avoid repeated computations in the future.
if (n < MAX) m[n] = temp; return temp; }
The main part of the program. Read the input data.
scanf("%lld %lld %lld %lld %lld",&n,&p,&q,&x,&y);
Compute and print the answer.
res = f(n,p,q,x,y); printf("%lld\n",res);
Given two integers and , find a real number such that the value of is maximized. It is known that
It can be proven that the maximum value of the function is rational. Print this value in the form of an irreducible fraction.
Input. Contains no more than test cases. Each test case consists of a single line containing two integers and .
Output. For each test case, print the maximum value of in the form of an irreducible fraction , where .
1 1 1 2
1/2 1/4
Let’s consider the values that the expression takes, where for fixed and . For example, .
Let’s consider, for instance, the function . Then
According to the extended Euclidean algorithm, there always exist integers and , such that . Therefore, the smallest positive value that the expression can take is . From this, it follows that this expression can take all possible values of the form , where .
Theorem. If , then this function takes values of the form , where .
Proof. Indeed,
Since the numbers and are coprime, there always exists integers and such that the numerator of the fraction equals . Therefore, the function can take all possible values of the form , where .
Now let's consider the original function
Its values are the distances from the point to the nearest point of the form , where . To maximize the function , the value of should be chosen so that it is exactly in the middle between the neighboring points and , where is an integer. The value of the function at such a point is , which will be the answer.
Example
Let . It is obvious that . The equality holds because there exist integers and such that (for example, ). From this, it also follows that , where .
However, , and this will be the maximum value of the function, as the point is at the maximum distance from the zeros of the function.
The gcd function computes the greatest common divisor of the numbers and .
long long gcd(long long a, long long b) { return b == 0 ? a : gcd(b, a % b); }
The lcm function computes the least common multiple of the numbers and .
long long lcm(long long a, long long b) { return a / gcd(a, b) * b; }
The main part of the program. Read the input data.
while (scanf("%lld %lld", &n, &m) == 2) {
Compute and print the result.
d = 2 * lcm(n, m); printf("%lld/%lld\n", 1, d); }
An array of integers is given. In how many ways can you choose a subset of its elements such that their sum is equal to ?
Input. The first line contains two integers: — the size of the array, and — the required sum.
The second line contains integers: — the elements of the array.
Output. Print a single integer — the number of ways to choose a subset of the array elements whose sum is equal to .
4 5 1 2 3 2
3
6 7 1 3 2 2 1 4
8
Divide the input array into two equal parts: and . Store the first part in array and the second in array .
First, solve the problem for sequence . Iterate over all possible subsets of (there will be at most of them). For each subset, calculate the sum of its elements , and increment the value by . As the data structure , we can use, for example, an unordered_map. Thus, will contain the number of ways to choose a subset from array whose elements sum to .
Then, iterate over all subsets of array . Let be the sum of elements in one such subset. If we combine this subset with all subsets of array whose sum is equal to , the result will be a subset of the original array whose elements sum to .
Example
Let's consider the second example. Divide the input sequence into two parts:
,
Iterate over all subsets of the set :
; | ; |
; | ; |
; | ; |
; | ; |
The structure will contain the following values after processing:
Now, iterate over all subsets of the set . In this example, the target sum is . For each sum corresponding to a subset of , add to the final answer.
;
;
;
;
;
;
;
;
The target sum is , which is the final answer.
Declare the data structures.
vector<int> a, b; unordered_map<long long, long long> m;
Read the input data. Store the first half of the sequence in array , and the second half in array .
scanf("%d %d", &n, &s); a.resize(n / 2); for (i = 0; i < n / 2; i++) scanf("%d", &a[i]); b.resize(n - n / 2); for (i = n / 2; i < n; i++) scanf("%d", &b[i - n / 2]);
Iterate over all subsets of sequence and compute the sum of their elements. In the unordered_map structure, keep track of how many times each sum occurs among these subsets. If is the sum of the current subset, then increment by .
for (i = 0; i < (1 << a.size()); i++) { sum = 0;
The variable contains the bitmask of the current subset of . The sum of its elements is computed in the variable .
for (j = 0; j < a.size(); j++) if (i & (1 << j)) sum += a[j];
For each obtained sum , increment the value of by .
m[sum]++; }
The number of ways to obtain the sum from the elements of the original array is counted in the variable .
res = 0;
Iterate over all subsets of sequence .
for (i = 0; i < (1 << b.size()); i++) { sum = 0;
The variable contains the bitmask of the current subset of . The sum of the elements in this subset is computed in the variable .
for (j = 0; j < b.size(); j++) if (i & (1 << j)) sum += b[j];
If we combine the current subset of set , whose sum of elements is , with all subsets of set a whose sum is , the result will be a subset of the original array whose sum of elements is equal to .
if (m.count(s - sum) > 0) res += m[s - sum]; }
Print the answer.
printf("%lld\n", res);
Genetic scientists from the planet Olympia are once again conducting experiments with the DNA of primitive organisms. The genome of an organism is a sequence of genes, each of which can be encoded by a natural number. Genes encoded by the same number are considered identical, while genes encoded by different numbers are considered different.
The scientists have already created a primitive organism and want to modify its genome in such a way as to produce an ideal organism. They believe that this will help develop cures for many diseases in the future.
An organism is considered ideal if any two identical genes are either located on adjacent positions in the genome or have at least one identical gene between them.
In one operation, scientists can select one or more identical genes in the genome, remove them, and then place them back into the genome, possibly at different positions. Since each such operation weakens the organism, the scientists aim to minimize the number of operations needed to achieve their goal.
Write a program that, given a representation of the genome, determines the minimum number of operations required to create an ideal organism.
Input. The first line contains the number of genes in the genome of a primitive organism. The second line contains positive integers, each of which does not exceed — the sequence of genes in the genome.
Output. Print the minimum number of operations required to create an ideal organism.
1 2 1 3 1 3 2 4 5
2
The gene rearrangement should be performed in such a way that identical genes are placed next to each other. At the same time, it is necessary to minimize the number of operations performed.
For each positive integer , we associate an interval , where is the position where first appears, and is the position where appears for the last time.
Let be the maximum possible number of non-overlapping intervals. This value can be found using the "activity-selection" algorithm, which means that each of the remaining intervals overlaps with at least one of the selected intervals. After this, the described procedure should be applied to the genes corresponding to these intervals.
If is the total number of constructed intervals, then the answer to the problem will be .
Example
For the given example, the intervals will look like this (position numbering starts from zero):
for ;
for ;
for ;
for ;
for ;
Let's sort the intervals by their end coordinate:
The maximum number of non-overlapping intervals is . For example, we can select the intervals . For the genes corresponding to the remaining intervals, the procedure described in the problem statement should be applied. The corresponding genes are and . Two rearrangements can be performed, for example, as follows:
Let be the maximum possible number of genomes in the input sequence.
#define MAX 100001
The vector of pairs stores the segments .
vector<pair<int, int> > v; int s[MAX], e[MAX];
Read the input data. Initialize .
scanf("%d", &n); memset(s, -1, sizeof(s)); memset(e, -1, sizeof(e)); for (i = 0; i < n; i++) { scanf("%d", &x);
If the number appears for the first time, record its position in the input sequence in .
if (s[x] == -1) s[x] = i;
If the number does not appear for the first time, record its position in , assuming that appears for the last time.
if (i > e[x]) e[x] = i; }
All the constructed intervals are stored in the vector .
for (i = 1; i <= n; i++) // numbers 1..n if (s[i] != -1) v.push_back(make_pair(e[i], s[i]));
The intervals are stored in the vector in reverse order (in the form ) so that, by default, the intervals are sorted in ascending order of their ends.
sort(v.begin(), v.end());
Find the maximum number of non-overlapping intervals.
i = res = 0; while (i < v.size()) {
Add the -th interval to the set of non-overlapping intervals. The variable holds the end of this interval (let's call it the current interval).
res++; temp = v[i++].first; // end
As long as the start of the next interval is less than the end of the current interval, skip such an interval, as it overlaps with the current one.
while (i < v.size() && v[i].second < temp) i++; }
Print the answer.
printf("%d\n", v.size() - res);
The army of the Polish–Lithuanian Commonwealth is marching from the city of Kostroma to the village of Domnino. The army is led by two hetmans — Stefan and Konstantin.
Stefan has a map of the Kostroma region, which shows all the roads between villages. Each night, he leads the army from one village to another using one of these roads. Konstantin, on the other hand, has obtained a map of secret trails, and during the day, he leads the army along one of these paths. Before each movement, each hetman consults the guide, Ivan Susanin, to determine the best route.
Stefan's map shows the length of each road, so he can calculate the shortest distance from any village to Domnino using his map. Similarly, Konstantin knows the shortest distances according to his map of trails.
Ivan Susanin, being a secret agent, wants to avoid raising suspicion. Therefore, each time he selects a road (for Stefan) and a trail (for Konstantin) such that the shortest distance to the village of Domnino, according to the respective hetman's map, strictly decreases.

Help Ivan determine the maximum possible length of the route to the village of Domnino.
Input. The first line contains three integers , , and — the number of villages in the Kostroma region, the starting village number, and the village number of Domnino, respectively. Villages are numbered from to . It is guaranteed that .
Then follow two blocks, each describing a map: the first block is Stefan’s map, the second one is Konstantin’s.
The first line of each block contains an integer — the number of roads or trails. Each of the following lines contains three integers , , and describing a connection between villages and of length .
Movement along roads and trails is allowed in both directions. It is guaranteed that each map allows travel between any pair of villages. The army begins its journey in the evening from village , traveling one road per night and one trail per day.
Output. Print a single integer — the maximum possible length of the route to village Domnino (considering alternating road and trail movement). If Ivan Susanin can lead the army indefinitely without reaching Domnino, print "".
5 1 5 5 1 2 2 1 4 2 2 3 1 3 4 1 5 3 1 4 1 2 2 2 4 2 2 3 1 2 5 2
-1
3 1 3 4 1 2 10 2 3 10 1 3 20 2 3 30 4 2 1 10 1 3 10 1 1 10 2 3 10
20
Сonstruct two graphs: the road graph and the trail graph . Next, compute the shortest distances from the village Domnino to all villages:
According to Stefan's map: — the minimum distance from to village ;
According to Konstantin's map: — the minimum distance from to village ;
Then consider a graph whose vertices are pairs :
— the village number;
(night, movement along roads), (day, movement along trails).
The army starts its journey in the evening from the initial village, moving at night along a road . Run a depth-first search from the vertex following these rules:
from (night) go along a road to if ;
from (day) go along a trail to if .
Being in the state , consider only allowed transitions — that is, those for which the distance to Domnino strictly decreases. Among these, look for the path of maximum length.
Recall that each of the hetmans tries to move so that the distance according to their own map decreases (however, they are not required to follow the shortest path).
During the depth-first search, maintain the following dynamic programming state:
— the maximum length of a path from to , starting from phase .
For each allowed transition:
Recursively call — transition to the opposite phase.
Update the value of :
Thus, we choose the best next move that leads to the maximum total path length. This is analogous to the standard longest path search in a DAG (directed acyclic graph), where the direction of edges is determined by the decrease in shortest distance.
Movement is allowed only along edges leading to vertices with a smaller distance to Domnino. However, the problem involves two graphs — two types of edges: roads and trails — and transitions between them alternate: night (road), day (trail), night, day, and so on. It is precisely because of this alternation of maps (roads and trails) that a cycle may arise between vertices, even though in each individual graph (for one map) the movement always goes along decreasing distances.
If during the depth-first search we encounter a vertex that is already in the processing stack, it means a cycle has been detected.
Declare the constants.
#define INF 2e18 #define MAXN 1005
Let's declare the data structures used:
and — adjacency lists for the road and trail graphs, respectively.
and — shortest distances from the village Domnino to all other villages.
and — the maximum path length from vertex to , if starting from along the road or along the trail .
and — vertex visitation markers for depth-first search in the road and trail graphs, respectively.
vector<pair<int, int>> g[2][MAXN]; long long d[2][MAXN]; long long dp[2][MAXN]; int used[2][MAXN];
The function dijkstra calculates the shortest distances from the village Domnino to all other villages either along the roads or along the trails .
void dijkstra(int type) { for (int i = 1; i <= n; i++) d[type][i] = INF; d[type][t] = 0; priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq; pq.push({ 0, t }); while (!pq.empty()) { pair<long long, int> top = pq.top(); pq.pop(); long long dist = top.first; int v = top.second; if (dist > d[type][v]) continue; for (auto edge : g[type][v]) { int to = edge.first; int w = edge.second; if (d[type][to] > d[type][v] + w) { d[type][to] = d[type][v] + w; pq.push({ d[type][to], to }); } } } }
The dfs function performs a depth-first search and finds the longest path while moving through alternating maps, starting from village along the road or along the trail . If during such alternating movement a cycle is detected, the function returns .
void dfs(int v, int type) {
Vertex in the graph is marked as gray.
used[type][v] = 1;
Initialize the dynamic programming state.
dp[type][v] = 0;
Iterate over the edges outgoing from vertex in the graph .
for (auto edge : g[type][v]) { int to = edge.first; int weight = edge.second;
A transition from vertex to vertex is allowed only if the distance from to Domnino is less than the distance from to Domnino.
if (d[type][to] < d[type][v]) {
If the vertex in the graph is already in the process of being visited (marked as "gray"), then a cycle has been detected — return .
if (used[type ^ 1][to] == 1) { cout << -1 << endl; exit(0); }
If the vertex in the graph has not yet been visited, continue the depth-first search from it.
if (used[type ^ 1][to] == 0) dfs(to, type ^ 1);
After processing all allowed transitions, update the dynamic programming state by selecting the maximum path length from vertex in the graph to Domnino.
dp[type][v] = max(dp[type][v], dp[type ^ 1][to] + weight); } }
Vertex in the graph is marked black.
used[type][v] = 2; }
The main part of the program. Read the input data and construct the road and trail graphs.
scanf("%d %d %d", &n, &s, &t); scanf("%d", &m1); for (i = 0; i < m1; i++) { scanf("%d %d %d", &a, &b, &len); g[0][a].push_back({ b, len }); g[0][b].push_back({ a, len }); } scanf("%d", &m2); for (i = 0; i < m2; i++) { scanf("%d %d %d", &a, &b, &len); g[1][a].push_back({ b, len }); g[1][b].push_back({ a, len }); }
Calculate the shortest distances from the village Domnino to all other villages — separately for the road map and for the trail map.
dijkstra(0); dijkstra(1);
Using depth - first search, find the longest path while moving through alternating maps, starting from the village along the road.
dfs(s, 0);
Print the answer. The starting point is village , and the movement begins on the road.
printf("%lld\n", dp[0][s]);
Alice is a magician, and she creates a new trick. She has cards with different numbers from to written on them. First, she asks an audience member to shuffle the deck and put the cards in a row. Let the number on the -th card from the left be .
Then Alice selects two permutations and . There is a restriction on and : permutations can’t have fixed points. In other words, and .
Once permutations are chosen, Alice shuffles the cards according to them. Now the -th card from the left becomes the card . The trick is considered successful if, after shuffling, the number on the -th card from the left is .
Help Alice choose the permutations and , or determine if it is impossible for the given starting permutation .
Input. The first line contains the number of test cases .
Each test is described in two lines. The first line contains one integer — the number of cards. The second line contains integers — the initial permutation of the cards.
It is guaranteed that the sum of over all tests does not exceed .
Output. Print the answer for each test case in the order they appear in the input.
For each test case, print “Impossible” on a single line if no solution exists.
Otherwise, print "Possible" on the first line, followed by two lines containing the permutations and .
4 2 2 1 3 1 2 3 4 2 1 4 3 5 5 1 4 2 3
Impossible Possible 3 1 2 2 3 1 Possible 3 4 2 1 3 4 2 1 Possible 4 1 2 5 3 3 1 4 5 2
Let’s consider three permutations: , and . Let be the identity permutation. Consider the equation: . From this, we get . Using the fact that permutations are applied from right to left, this identity can be rewritten as: . Therefore, .
Generate a random permutation that has no fixed points. Then, compute the permutation and check that it has no fixed points. The found permutations and are the required ones.
Example
Consider the permutation .
Its inverse will be .
Generate a random permutation with no fixed points. For example, let . Now, let's compute its inverse: .
Next, compute . The permutation has no fixed points, so it is valid.
The print function prints the elements of the array , starting from the first one.
void print(vector<int>& a) { for (int i = 1; i < a.size(); i++) printf("%d ", a[i]); printf("\n"); }
The function is_valid checks whether the permutation contains any fixed points.
bool is_valid(vector<int>& v) { for (int i = 1; i < v.size(); i++) if (v[i] == i) return false; return true; }
Declare the arrays.
vector<int> a, p, p1, q;
The main part of the program. Read the input data.
scanf("%d", &tests); while (tests--) { scanf("%d", &n);
Initialize the arrays.
a.resize(n + 1); p1.resize(n + 1); p.resize(n + 1); q.resize(n + 1);
Read the input permutation and immediately store its inverse in the array . That is, the array contains the permutation , where is the input permutation.
for (i = 1; i <= n; i++) { scanf("%d", &x); a[x] = i; }
mt19937 is one of the standard pseudorandom number generators in C++ (Mersenne Twister with a period of 19937). It is very fast and has good statistical properties, making it an excellent choice for most tasks requiring random number generation.
mt19937 gen(random_device{}());
In the variable , we'll mark whether a solution is found for the current test.
found = false;
Perform iterations.
for (it = 0; it < 1000; it++) {
Generate a random permutation. To do this, populate the array with the numbers , and use the shuffle function to shuffle the elements, starting from the first (non-zero) element. We work with permutations from to .
iota(p.begin(), p.end(), 0); shuffle(p.begin() + 1, p.end(), gen);
Check whether the permutation is valid (i.e., it contains no fixed points).
if (!is_valid(p)) continue;
Compute the permutation .
for (i = 1; i <= n; i++) p1[p[i]] = i;
Compute the permutation .
for (i = 1; i <= n; i++) q[i] = p1[a[i]];
If the permutation is valid, print the result.
if (is_valid(q)) { puts("Possible"); print(p); print(q); found = true; break; } }
If no solution is found after iterations, then no solution exists.
if (!found) puts("Impossible"); }