Basecamp
    Головна
    Задачі
    Змагання
    Курси
    Рейтинг
    Дописи
    Магазин
    Discord
Educational Round #5 — Editorial
Увійти
Розбори•1 день тому

Educational Round #5 — Editorial

Eolymp #911. Quadratic equation

Solve the quadratic equation a⋅x2+b⋅x+c=0 (a=0).

Input. One line contains three integers — the coefficients of the quadratic equation a,b, and c. The absolute values of all coefficients do not exceed 100.

Output. Print on a single line:

  • "No roots" if the equation has no roots;

  • "One root:" followed by the root, separated by a space, if the equation has one root;

  • "Two roots:" followed by the smaller root and the larger root, separated by a space, if the equation has two roots.

It is guaranteed that if solutions exist, all roots are integers.

Sample input 1
1 -5 6
Sample output 1
Two roots: 2 3
Sample input 2
1 2 10
Sample output 2
No roots
Open problem
Solution

The task is to solve the quadratic equation using the formula

x=2a−b±d​​,

where d is the discriminant of the quadratic equation, equal to b2−4ac.

Depending on the sign of the discriminant, there are three possible cases:

  • d<0: the equation has no roots;

  • d=0: the equation has one root;

  • d>0: the equation has two roots, which should be printed in ascending order.

Algorithm implementation

Since the coefficients of the equation and its roots (if they exist) are integers, all computations will be performed using integers. Read the input data.

scanf("%d %d %d", &a, &b, &c);

Compute the discriminant of the quadratic equation.

d = b * b - 4 * a * c;

Depending on the sign of the discriminant, print the answer.

if (d < 0) 
  printf("No roots\n");
else if (d == 0) 
{
  x1 = -b / (2 * a);
  printf("One root: %d\n", x1);
}
else 
{
  x1 = (-b - sqrt(d)) / (2 * a);
  x2 = (-b + sqrt(d)) / (2 * a);
  printf("Two roots: ");
  if (x1 < x2) 
    printf("%d %d\n", x1, x2);
  else 
    printf("%d %d\n", x2, x1);
}
C++
17 lines
315 bytes
Eolymp #1417. Queen Move

A queen is placed on an m×n chessboard. Determine how many squares are under its attack.

Input. Four positive integers: the size of the chessboard m and n, as well as the coordinates of the queen x and y (1≤x≤m≤109,1≤y≤n≤109).

Output. Print the number of squares under the queen's attack.

Sample input
8 8
4 5
Sample output
27
Open problem
Solution

The queen is a chess piece that moves (and attacks) horizontally, vertically, and diagonally.

The row where the queen is placed contains n squares, so the number of squares available for horizontal movement is n−1. Similarly, the column where the queen is located contains m squares, meaning the number of squares available for vertical movement is m−1.

Thus, the number of squares under the queen's attack horizontally and vertically is n−1+m−1.

Divide the board into four areas by drawing horizontal and vertical lines through the square where the queen is located. In each of these areas, count the number of squares under her attack.

Consider, for example, the upper-right quadrant. Its length is n−y squares, and its width is x−1 squares. Therefore, the number of squares under the queen's attack in this area is min(x−1,n−y).

Similarly:

  • In the upper-left quadrant, there are min(x−1,y−1) squares;

  • In the lower-left quadrant, there are min(m−x,y−1) squares;

  • In the lower-right quadrant, there are min(m−x,n−y) squares;

Example

Consider the example where the board size is 8×8 and the queen is located at position (4,5).

The number of squares under the queen's horizontal and vertical attack is n−1+m−1=7+7=14. Now, let's consider the four quadrants, in each of which we'll count the number of squares under its attack:

  • in the upper left quadrant there are min(4,3)=3 squares;

  • in the lower left quadrant there are min(4,4)=4 squares;

  • in the lower right quadrant there are min(3,4)=3 squares;

  • in the upper right quarter there are min(3,3)=3 squares;

Thus, the total number of squares under the queen's attack is

14+3+4+3+3=27
Algorithm implementation

Read the input data.

scanf("%d %d %d %d", &m, &n, &x, &y);

Store in the variable s the number of squares under the queen's attack from horizontal and vertical moves.

s = m - 1 + n - 1; // horiz & vertical

Then, add the squares that the queen attacks along the diagonals.

s += min(m - x, n - y); // (x,y) = (m, n)
s += min(m - x, y - 1); // (x,y) = (m, 1)
s += min(x - 1, n - y); // (x,y) = (1, n)
s += min(x - 1, y - 1); // (x,y) = (1, 1)

Print the answer.

printf("%lld\n",s);
Eolymp #7714. Milling machines

A Fab Lab is a small open workshop where you can create or manufacture almost anything you want, mainly using computer-controlled tools such as a laser cutter or a 3D printer. Recently, the FAU Fab Lab acquired a CNC milling machine. With this machine, you can cut or remove material from the surface of a workpiece using various tools. The entire process is controlled by a computer program.

Sometimes I wondered what would happen if several workpieces of different shapes were processed using the same milling program. To simplify the situation, let's assume that we only have two-dimensional workpieces without holes. A milling program consists of several steps, each describing which parts of the surface the milling machine should remove material from (using different tools).

Input. The first line contains two integers w and s (1≤w,s≤104) — the number of workpieces and the number of steps in the milling program.

The next line contains two integers x and y (1≤x,y≤100), where x is the width of a workpiece, and y is its maximum possible height.

Each of the following w lines describes one workpiece. The description of each workpiece consists of x non-negative integers defining the surface height in each column.

Then follow s lines describing the milling steps. Each milling step consists of x non-negative integers si​ (0≤si​≤y), determining how much material should be removed in each column (relative to the milling area height, i.e., relative to y, not to the top of the workpiece). See the illustration.

Output. For each workpiece, print one line containing x integers — the remaining surface heights after all milling steps (in the same order as in the input).

Examples. In the first example, you can see how the second workpiece looks after applying all milling steps sequentially: each value in the program defines the vertical position of the milling head.

Sample input 1
2 1
3 4
4 4 4
4 2 3
2 3 0
Sample output 1
2 1 4
2 1 3
Sample input 2
1 3
10 100
11 22 33 44 55 66 77 88 99 100
1 100 1 100 1 100 1 100 1 100
58 58 58 58 58 58 58 58 58 58
42 42 42 42 42 42 42 42 66 42
Sample output 2
11 0 33 0 42 0 42 0 34 0
Open problem
Solution

The milling program consists of s steps. Let at the i-th step (1≤i≤s) a layer of thickness mij​ be removed from the surface in column j (1≤j≤x). It is clear that the total amount removed in column j will be

max(m1j​,m2j​,...,msj​)

We’ll call the milling scheme the set of integers

(cuts1​,cuts2​,...,cutsx​),

where

cutsj​=max(m1j​,m2j​,...,msj​),1≤j≤x

The same milling scheme is applied to all w workpieces. After computing the values of cutsj​ (1≤j≤x), this scheme is then applied sequentially to each workpiece.

Algorithm implementation

Declare the arrays. The information about the workpieces is stored in the array detail, and the milling scheme is stored in the array cuts.

int detail[10001][101], cuts[101];

Read the input data.

scanf("%d %d %d %d", &w, &s, &x, &y);

Read the information about the w workpieces.

for (i = 0; i < w; i++)
for (j = 0; j < x; j++)
  scanf("%d", &detail[i][j]);

Read and process the s steps of the milling program. For each position j, the value cuts[j] represents the maximum cutting depth achieved at any of the steps.

for (i = 0; i < s; i++)
for (j = 0; j < x; j++)
{
  scanf("%d", &val);
  if (val > cuts[j]) cuts[j] = val;
}

The maximum possible height of a workpiece is y. The milling head at position j is lowered to a depth of cuts[j]. Consequently, after milling, the remaining height of the i-th workpiece at position j will be equal to

min(detail[i][j],y−cuts[j]).
for (i = 0; i < w; i++)
{
  for (j = 0; j < x; j++)
    printf("%d ", min(detail[i][j], y - cuts[j]));
  printf("\n");
}
Eolymp #11460. K-th Gutab

At ADA University, there are n types of gutabs available for sale. A gutab of type i costs ai​ qəpiks.

Gutab is an Azerbaijani dish made from thinly rolled dough, quickly cooked on a convex griddle known as a saj. There are many variations of gutab: typically, the filling consists of pumpkin and herbs. Other regional types include Shamakhi gutab, yashyl gutab, karyn gutab, guzu gutab (with lamb), and deve gutab — traditional varieties commonly found in the village of Jorat and other regions of Azerbaijan.

Huseyn intends to buy at least one gutab. He is allowed to purchase multiple gutabs of the same type.

Find the k-th smallest possible price Huseyn may pay. If there are several combinations of gutabs that result in the same total price, that price is counted only once.

Input. The first line contains two integers: n (1≤n≤10) and k (1≤k≤2⋅105).

The second line contains n integers — the prices of the different types of gutabs: a1​,a2​,…,an​ (1≤ai​≤109).

Output. Print the k-th smallest price Huseyn can pay.

Examples. The six smallest prices Huseyn can pay:

  • 5 qəpik

  • 10 qəpik

  • 11 qəpik

  • 15 qəpik

  • 11 + 5 = 16 qəpik

  • 20 qəpik

Thus, the answer is 20.

Sample input
5 6
5 10 11 15 20
Sample output
20
Open problem
Solution

Add the number 0 to the set. Then perform k steps:

  • Find the smallest element x in the set and remove it.

  • For each i from 1 to n, add the element x+ai​ to the set.

After performing k steps, the smallest element in the set will be equal to the k-th smallest price Huseyn can pay.

Algorithm implementation

Read the input data.

scanf("%d %d", &n, &k);
for (i = 0; i < n; i++)
  scanf("%d", &m[i]);

Add the number 0 to the set s.

s.insert(0);

Perform k iterations.

for (i = 0; i < k; i++)
{

Find and remove the smallest element x from the set.

  x = *s.begin(); s.erase(x);

For each i from 1 to n, add the element x+ai​ to the set.

  for (j = 0; j < n; j++)
    s.insert(x + m[j]);
}

Print the answer: the k-th smallest price, which is equal to the smallest element in the set.

printf("%lld\n", *s.begin());
Eolymp #10455. Linear network

A linear network consisting of n computers was installed in a big data processing center. All computers are numbered consecutively with integers from 1 to n. There is a direct connection between any two computers with consecutive numbers. Clearly, in such a network, data can be exchanged between any two computers, either directly or through intermediate ones.

However, due to the high workload, some computers may fail. In such cases, connections between certain computers are disrupted, making data transfer between them impossible.

Your task is to determine the current number of groups in the network. A group is defined as the largest subset of active computers where any two computers are connected either directly or through other computers. A group can also consist of a single computer.

You need to answer q queries. Each query either reports the failure of one of the computers or requests the current number of groups.

Input. The first line contains two integers n (1≤n≤109) and q (1≤q≤105) — the number of computers and the number of queries, respectively. Each of the following q lines represents a query.

Each query starts with an integer T, indicating its type. If T=1, it is followed by an integer L (1≤L≤n), which is the number of the computer that has failed.

  • A query of type T=1 indicates that the computer numbered L has failed.

  • A query of type T=2 requests the current number of groups in the network.

Output. For each query of the second type (T=2), print the current number of groups in the network on a separate line.

Examples. 1 2 3 4 — Initial state of the network. The number of groups is 1.

1 x 3 4 — The state of the network after the failure of the computer number 2. Number of groups — 2.

1 x 3 x — The state of the network after the failure of the computer number 4. Number of groups — 2.

1 x 3 x — The state of the network after the failure of the computer number 2. Number of groups — 2.

The requests for computer failure may be repeated.

Sample input
4 6
1 2
2
1 4
2
1 2
2
7 lines
29 bytes
Sample output
2
2
2
Open problem
Solution

The computers are numbered from 1 to n. Since n≤109, store the status of working and failed computers in a map map<int,int>m. The value of m[i]=0 if the computer with number i is working, and m[i]=1 if it is broken. Initially, for all 1≤i≤n, set m[i]=0

For convenience, we introduce two dummy broken computers with numbers 0 and n+1. Set m[0]=m[n+1]=1.

The number of groups of computers in the network will be maintained in the variable cnt. Initially, there is one group in the network, so set cnt=1.

Now let's consider the process of handling q queries. In particular, let's examine the failure of the computer with number l (query type t=1):

  • If both the computer's neighbors, on the right and left, are broken, the number of groups decreases by 1. This is because computer l, which previously represented a group of a single device, has failed.

  • If both the computers to the right and left of computer l are working, the number of groups will increase by 1.

  • In all other cases, the number of groups remains unchanged.

For processing a query of type t=2, it is sufficient to print the current value of the variable cnt.

Example

Algorithm implementation

Declare a data structure map.

map<int, int> m;

Read the number of computers n and the number of queries q.

scanf("%d %d", &n, &q);

Initialize the dummy computers with numbers 0 and n+1.

m[0] = 1;
m[n + 1] = 1;

Maintain the number of groups of computers in the network in the variable cnt. Initially, all computers are operational, so cnt=1.

cnt = 1;

Sequentially process q queries.

while (q--)
{
  scanf("%d", &t);
  if (t == 1)
  {

Query t=1. The computer with number l fails. If computer l is already broken, no action is required.

    scanf("%d", &l);
    if (m[l] == 0)
    {

Otherwise, set the state of computer l as broken.

      m[l] = 1;

Depending on the state of the neighboring computers of l (either working or broken), recompute the number of groups:

  • If both neighboring computers are broken, decrease cnt by 1;

  • If both neighboring computers are working, increase cnt by 1;

      k = m[l - 1] + m[l + 1];
      if (k == 2) cnt--;
      else if (k == 0) cnt++;
    }
  }
  else

For query t=2, print the current number of groups of computers in the network.

    printf("%d\n", cnt);
}
Eolymp #1575. God! Save me

You are in a room with n doors. If you open the door numbered i, then after xi​ hours you will either reach a safe place or return to this same room. Calculate the expected time P (in hours) after which you can escape the room to a safe place.

Input. The first line contains the number of tests. The first line of each test contains the number of doors n (0<n<100). Each of the following n lines contains two numbers xi​ (0<∣xi​∣<25) and pi​ (0≤pi​≤1).

  • If xi​ is positive, it represents the time after which you can reach a safe place;

  • If xi​ is negative, then ∣xi​∣ represents the time after which you will find yourself back in the room;

Here, pi​ is the probability of opening the i-th door. The sum of all pi​ equals 1.

Output. For each test, print its number, a colon, a space, and then:

  • the phrase "God! Save me" if it is impossible to escape from the room;

  • or the expected time P with 6 decimal places, after which you can escape from the room to a safe place.

Sample input
3
3
2 0.33
-3 0.33
-5 0.34
3
2 0.34
-3 0.33
-5 0.33
3
10 0.0
-1 0.4
-1 0.6
13 lines
88 bytes
Sample output
Case 1: 10.151515
Case 2: 9.764706
Case 3: God! Save me
Open problem
Solution

Let P denote the expected time to escape the room to a safe place. This time is expressed as follows:

P=i=1∑n​pi​⋅ti​,

where ti​ is the time to reach a safe place if the i-th door is chosen. It is clear that ti​=xi​ if xi​>0. If xi​<0, then to escape, one must first spend time −xi​ to return to the room, and then spend time P for another attempt to exit. Thus, in this case, ti​=−xi​+P.

As a result, we obtain a linear equation in terms of P. This equation can be constructed and solved in O(n) time, where n is the number of doors.

Example

Let’s consider the first test. Create an equation:

P=0.33∗2+0.33∗(3+P)+0.34∗(5+P),

where from 0.33⋅P=3.35 or P=10.151515.

Algorithm implementation

We'll solve the linear equation as follows. All terms containing the multiplier P will be moved to the left side, and their coefficients will be stored in the variable left. All constants will be collected on the right side and stored in the variable right. Initially, set left=1 and right=0.

Read n pairs of numbers x and p.

  • If x>0, then increase the right side of the equation by x⋅p.

  • If x<0, a term p⋅(−x+P) will appear on the right side of the equation. In this case, we should add p⋅(−x) to the right side and subtract p from the left side.

left = 1.0; right = 0.0;
scanf("%d",&n);
for(j = 0; j < n; j++)
{
  scanf("%lf %lf",&x, &p);
  if (x < 0.0)
  {
    left -= p;
    right += p * (-x);
  } else
      right += x * p;
}
C++
12 lines
195 bytes

We obtained the equation left⋅P=right. If left=0, then it is impossible to escape from the room (there is no door leading to a safe place). Otherwise, the sought time can be calculated as P=right/left.

if (left > 0.0)
{
  res = right / left;

Print the answer. The variable i corresponds to the test number.

  printf("Case %d: %.2lf\n",i,res);
} else
  printf("Case %d: God! Save me\n",i);
Eolymp #11720. Jim and the Skyscrapers

Given an array h1​,h2​,...,hn​. Count the number of pairs of indices (i,j) (1≤i<j≤n) such that the following conditions hold: hi​=hj​ and i<k<jmax​hk​≤hj​.

Input. The first line contains one integer n (1≤n≤3⋅105). The second line contains n integers h1​,h2​,...,hn​ (1≤hi​≤106).

Output. Print the number of pairs of indices that satisfy the given conditions.

Examples. In the first example, the valid pairs are: (1,5),(1,6)(5,6) and (2,4).

Sample input 1
6
3 2 1 2 3 3
Sample output 1
4
Sample input 2
10
5 3 5 3 2 3 1 3 5 5
Sample output 2
9
Open problem
Solution

Imagine that we are building "walls" out of blocks of the same height.

A pair (i,j) forms a "corridor" if there is no taller block between these walls. To solve the problem, we'll use a monotone stack. The stack stores pairs (value,count):

  • value — the height of the wall (the value h[i]).

  • count — the number of consecutive elements of this height that have already appeared and can form pairs with future elements of the same height.

That is:

  • For each "block of identical numbers", we remember only two parameters: the number itself and how many times it has appeared consecutively so far.

  • When a new element appears, we can immediately determine how many pairs it forms: this number is exactly count for the element at the top of the stack.

For example, let the current number be a=5, and suppose it has already appeared 3 times (that is, the current occurrence of a=5 is the fourth one). Assume that between all these occurrences of a there are only smaller elements. Then the number of new index pairs (i,j), where j is the current index and the condition hi​=hj​=a holds, will be 3.

When processing the next number hi​:

  • If the number at the top of the stack is less than hi​, remove it from the stack.

  • If the number at the top of the stack is equal to hi​ and it has appeared previously x times, increase the target count of index pairs by x and update the number of occurrences of hi​ to x+1.

  • If the stack is empty or the number at the top of the stack is greater than hi​, push the pair (hi​,1) onto the stack. This means that the current value hi​ appears for the first time (it may have appeared earlier in the input sequence but was removed from the stack due to a larger element).

Example

Consider the first test case.

Algorithm implementation

Read the input data.

scanf("%d", &n);
vector<int> v(n);
for (i = 0; i < n; ++i)
  scanf("%d", &v[i]);

Store the number of found index pairs in the variable res.

res = 0;

Declare a stack of pairs.

stack<pair<int, int>> st;

Process all the numbers of the array sequentially.

for (i = 0; i < v.size(); i++)
{

While the number at the top of the stack is less than v[i], remove it from the stack.

  while (!st.empty() && st.top().first < v[i])
    st.pop();

If the number at the top of the stack is equal to v[i] and it has appeared previously x times (the value x is stored in st.top().second), increase the answer res by x. Then update the number of occurrences of v[i] to x+1.

  if (!st.empty() && v[i] == st.top().first)
  {
    res += st.top().second;
    st.top().second += 1;
  }
  else

If v[i] appears for the first time, push the pair (v[i],1) onto the stack.

    st.push({ v[i], 1 });
}

Print the answer.

printf("%lld\n", res);
Eolymp #1102. Sticks Problem

Xuanxuan has n sticks of different lengths. One day, she arranged them in a row, with lengths s1​,s2​,s3​,…,sn​. After measuring each stick sk​ (1≤k≤n), she noticed that for some pairs of sticks si​ and sj​ (1≤i<j≤n), the length of every stick placed between si​ and sj​ is strictly greater than si​ and strictly less than sj​.

Given the sequence of lengths s1​,s2​,s3​,…,sn​, find the maximum possible value of the difference j−i.

Input. Сonsists of multiple test cases. Each test case consists of two lines. The first line contains an integer n (n≤50000) — the number of sticks. The second line contains n distinct positive integers (not exceeding 105) — the lengths of the sticks.

Output. For each test case, print the maximum value of j−i on a separate line. If no such indices i and j exist, print −1.

Sample input
4
5 4 3 6
4
6 5 4 3
9
12 4 8 7 5 9 6 3 1
Sample output
1
-1
4
Open problem
Solution

For each index i, find the maximum index k (i≤k≤n) such that RMinQ(si+1​,...,sk​)>si​. This can be done using binary search. Next, the desired index j is defined as the position where the value RMaxQ(si​,...,sk​) is attained for i≤j≤k.

Thus, for each index i, we need to find the largest possible index j, and then, among all obtained pairs (i,j), determine the maximum difference j−i.

Example

Consider the third example.

Let i=2 (s2​=4). The largest index k=7 satisfies the condition RMinQ(si+1​,...,sk​)>4. The value of RMaxQ(s3​,...,s7​) is attained at index j=6.

Algorithm implementation

Let's declare the constants and arrays.

#define MAX 50010
#define LOGMAX 16
int dp_max[MAX][LOGMAX], dp_min[MAX][LOGMAX];
int a[MAX];

The function Build_RMQ_Array строит RMQ таблицы для быстрых запросов минимума (dp_min) и максимума (dp_max):

  • dp_min[i][j] stores the minimum value over the segment of length 2j starting at position i.

  • dp_max[i][j] stores the index of the element with the maximum value over the segment of length 2j starting at i.

void Build_RMQ_Array(int *b)
{
  int i, j;
  for (i = 1; i <= n; i++) 
  {
    dp_min[i][0] = b[i];
    dp_max[i][0] = i;
  }

  for (j = 1; 1 << j <= n; j++)
    for (i = 1; i + (1 << j) - 1 <= n; i++)
    {
      if (b[dp_max[i][j - 1]] > b[dp_max[i + (1 << (j - 1))][j - 1]])
        dp_max[i][j] = dp_max[i][j - 1];
      else
        dp_max[i][j] = dp_max[i + (1 << (j - 1))][j - 1];

      dp_min[i][j] = 
        min(dp_min[i][j - 1], dp_min[i + (1 << (j - 1))][j - 1]);
    }
}
C++
21 lines
507 bytes

The RangeMaxQuery function returns the index of the maximum element in the subsegment [i,j].

int RangeMaxQuery(int i, int j)
{
  int k = 0;
  while ((1 << (k + 1)) <= j - i + 1) k++; 

  if (a[dp_max[i][k]] > a[dp_max[j - (1<<k) + 1][k]])
    return dp_max[i][k];
  else
    return dp_max[j - (1<<k) + 1][k];
}
C++
10 lines
228 bytes

The RangeMinQuery function returns the minimum value in the subsegment [i,j].

int RangeMinQuery(int i, int j)
{
  int k = 0;
  while ((1 << (k + 1)) <= j - i + 1) k++; 
  return min(dp_min[i][k],dp_min[j - (1<<k) + 1][k]);
}

The BinSearch function uses binary search on the interval [Left;Right] to find the largest index k such that all elements between Left+1 and k are greater than a[Left].

int BinSearch(int Left, int Right)
{
  int MinValue = a[Left++];
  if (RangeMinQuery(Left,Right) > MinValue) return Right;

  while (Right > Left)
  {
    int Middle = (Left + Right) / 2;
    if (RangeMinQuery(Left,Middle) > MinValue)
      Left = Middle + 1;
    else
      Right = Middle;
  }

  if (dp_min[Left][0] <= MinValue) Left--;
  return Left;
}
C++
17 lines
373 bytes

The main part of the program. Process the test cases sequentially.

while(scanf("%d",&n) == 1)
{
  for(i = 1; i <= n; i++) scanf("%d",&a[i]);

Build the RMinQ and RMaxQ arrays.

  Build_RMQ_Array(a);

For each index i:

  • Using BinSearch(i,n), find the largest index k such that all elements in the interval [i+1;k] are greater than a[i];

  • In the interval [i,k] find the index j where the maximum value is reached.

  • Check whether j−i is the largest difference.

  res = 0;
  for(i = 1; i <= n; i++)
  {
    k = BinSearch(i, n);
    j = RangeMaxQuery(i,k);
    if (j - i > res) res = j - i;
  }
C++
7 lines
139 bytes

Print the result. If res=0, we should print −1.

  if (res == 0) res = -1;
  printf("%d\n",res);
}
Eolymp #10292. Moortal Cowmbat

Bessie has been playing the popular game Moortal Cowmbat for a long time. However, the game developers have recently released an update that forces her to change her usual play style.

The game uses m buttons, labeled with the first m lowercase letters of the Latin alphabet. Bessie’s favorite combination of moves is a string s of length n, describing a sequence of button presses. After the update, each combo must consist of a sequence of "stripes", where a stripe is defined as a consecutive sequence of the same button pressed at least k times in a row. Bessie wants to modify her favorite combination to obtain a new string of the same length n, but consisting of stripes that satisfy the updated rules.

It is known that Bessie needs aij​ days to learn to press button j instead of button i in any specific position of her combination (that is, replacing one occurrence of letter i in s with letter j costs aij​ days).

Note that sometimes the replacement can be done faster through intermediate buttons. For example, changing i directly to j may be more expensive than performing two consecutive replacements i→k→j. Thus, there may exist a transformation path from i to j with a smaller total cost than the direct replacement.

Help Bessie determine the minimum number of days required to create a combination that satisfies the new requirements.

Input. The first line contains three integers: n (1≤n≤105), m (1≤m≤26), and k (1≤k≤n).

The second line contains the string s.

The next m lines each contain m integers — the elements of the matrix aij​, where aij​ is the number of days required to replace button i with button j. It is guaranteed that 0≤aij​≤1000 and aii​=0 for all i.

Output. Print the minimum number of days Bessie needs to create a combination that meets the new requirements.

Example. In this example, the optimal solution is to replace a with b, then replace d with e, and finally replace both e's with c. The total cost of these changes is 1+4+0+0=5 days, and the resulting string will be bbccc.

Sample input
5 5 2
abcde
0 1 4 4 4
2 0 4 4 4
6 5 0 3 2
5 5 5 0 4
3 7 0 5 0
7 lines
69 bytes
Sample output
5
Open problem
Solution

Let's run the Floyd – Warshall algorithm on the matrix aij​ to determine the shortest time required to replace each letter with any other letter.

Then construct a cost matrix cst, where cst[i][j] (1≤i≤n) represents the minimum number of days needed to change the letter s[i−1] into the letter j.

For convenience in further calculations, we build a matrix ps that contains the column-wise prefix sums of the cost matrix cst:

ps[i][j]=cst[i][1]+cst[i][2]+...+cst[i][j]

Let dp[i][j] denote the minimum number of days required to transform the first i letters of the string s into a string that satisfies Bessie’s new requirements, with the last k letters of the new string being the letter j.

We can write the dynamic equations as follows:

  • Suppose the first i−1 letters of s уhave already been transformed into a string whose last k letters are all j. Then we simply change the letter s[i−1] to j, which can be done in cst[i][j] days.

    dp[i][j]=dp[i−1][j]+cst[i][j]
  • To ensure that the last k letters of the new string are all j, consider the values dp[i−k][0],dp[i−k][1],...,dp[i−k][m−1]. Choose the smallest among them — that is, we transform the first i−k letters of s into a string satisfying Bessie's new requirements (we don't care which letter the substring of length i−k ends with; we only care that it can be obtained in the minimum number of days). After that, we replace the last k letters of the original string s — namely s[i−k],s[i−k+1],...,,s[i−1] — with the letter j, which takes

cst[i−k+1][j]+cst[i−k+2][j]+...+cst[i][j]

days. This sum can be computed in constant time using the prefix sum array ps:

cst[i−k+1][j]+cst[i−k+2][j]+...+cst[i][j]=ps[i][j]−ps[i−k][j]

We maintain an auxiliary array mn, where

mn[i]=min(dp[i][0],dp[i][1],...,dp[i][m−1])

Thus, the dynamic programming equation for this case (i≥k) takes the following form:

dp[i][j]=ps[i][j]−ps[i−k][j]+mn[i−k]

It remains to choose the smaller of the two options for dp[i][j].

The answer to the problem is the value

mn[n]=min(dp[n][0],dp[n][1],...,dp[n][m−1])

We don't care which particular k letters the new word Bessie ends with.

Example

In this example, the optimal solution is as follows: replace a with b, then d with e, and after that replace both e's with c. The total cost of the changes is 1+4+0+0=5 days, and the resulting string will be bbccc.

Using the matrix aij​, we construct the cost matrix cst. We also compute the matrix ps.

All values of dp[1][j] (0≤j≤4) will be equal to +∞, since the length of the stripe cannot be less than k=2. Accordingly, mn[1]=+∞.

Let us now consider the process of computing the values of dp[2][j] (0 ≤ j ≤ 4).

  • dp[2][0]=("ab"→"aa")=cnt['a']['a']+cnt['b']['a']=0+2=2;

  • dp[2][1]=("ab"→"bb")=cnt['a']['b']+cnt['b']['b']=1+0=1;

  • dp[2][2]=("ab"→"cc")=cnt['a']['c']+cnt['b']['c']=4+4=8;

  • dp[2][3]=("ab"→"dd")=cnt['a']['d']+cnt['b']['d']=4+4=8;

  • dp[2][4]=("ab"→"ee")=cnt['a']['e']+cnt['b']['e']=4+4=8;

mn[2]=min(dp[2][0],dp[2][1],dp[2][2],dp[2][3],dp[2][4])=1

When computing the values of dp[3][j] (0≤j≤4), the equation

dp[3][j]=ps[3][j]−ps[1][j]+mn[1]

will not be used, since mn[1]=+∞. Therefore, to obtain strips from the first three letters, one can only extend the strips of length two that have already been constructed:

  • dp[3][0]=dp[2][0]+cst['c']['a']=2+5=7 ("aaa");

  • dp[3][1]=dp[2][1]+cst['c']['b']=1+5=6 ("bbb");

  • dp[3][2]=dp[2][2]+cst['c']['c']=8+0=8 ("ccc");

  • dp[3][3]=dp[2][3]+cst['c']['d']=8+3=11 ("ddd");

  • dp[3][4]=dp[2][4]+cst['c']['e']=8+2=10 ("eee");

The value of dp[4][0] can be obtained in two ways:

  • dp[4][0]=dp[3][0]+cst['d']['a']=7+5=12 ("aaaa");

or

  • dp[4][0]=ps[4][0]−ps[2][0]+mn[2]=12−2+1=11 ("bbaa");

The second case is more optimal — two letters 'a' are appended to a two-character string. The value mn[2]=1 is achieved for the string "bb", which means the optimal string is "bbaa".

Algorithm implementation

Let us define the following arrays:

  • a[i][j] — the minimum cost of transforming letter i into letter j.

  • cst[i][j] — the cost of replacing the i-th letter of the original string s (indexing starts from 1) with letter j. Formally

    cst[i][j]=a[s[i−1]−′a′][j]
  • ps — the prefix sum array of cst, used to quickly compute the cost of changing a substring of length k:

    ps[i][j]=cst[1][j]+cst[2][j]+...+cst[i][j]
  • dp[i][j] — the minimum number of days required to transform the first i letters of string s into a valid string (according to the stripe rules), where the last k letters of the result are letter j.

  • mn[i] — the minimum over all j of dp[i][j], i.e. the best solution for the first i characters.

#define MAXN 100005
#define ALPH 26
int a[ALPH][ALPH], cst[MAXN][ALPH], ps[MAXN][ALPH], dp[MAXN][ALPH], mn[MAXN];

Read the input data.

cin >> n >> m >> k;
cin >> s;
for (i = 0; i < m; i++)
for (j = 0; j < m; j++)
   cin >> a[i][j];

Run the Floyd - Warshall algorithm on the matrix a. After it finishes, a[i][j] contains the minimum number of days required to change letter i into letter j.

for (x = 0; x < m; x++)
for (i = 0; i < m; i++)
for (j = 0; j < m; j++)
  a[i][j] = min(a[i][j], a[i][x] + a[x][j]);

We have m≤26 letters. Let us construct a cost matrix cst such that cst[i][j] (1≤i≤n) contains the minimum number of days required to change the letter s[i−1] into letter j. The letters in the string s are indexed starting from 0.

For convenience in further computations, we'll build a matrix ps, which contains the column-wise prefix sums of the cost matrix cst:

ps[i][j]=cst[i][1]+cst[i][2]+...+cst[i][j]
for (i = 1; i <= n; i++)
for (j = 0; j < m; j++)
{
  cst[i][j] = a[s[i - 1] - 'a'][j];
  ps[i][j] = ps[i - 1][j] + cst[i][j];
}

Initialize the arrays.

memset(dp, 0x3f, sizeof dp);
memset(mn, 0x3f, sizeof mn);
mn[0] = 0;

We compute the values of the dp array cells. The letter i corresponds to the character s[i−1]. The letters in variable j are numbered from 0 (corresponding to letter 'a') to m−1. Intuitively, at each step i, Bessie decides:

  • either to continue pressing the same button as before,

  • or to start a new stripe of length at least k.

We choose the cheaper option and save the result in dp[i][j].

for (i = 1; i <= n; i++)
for (j = 0; j < m; j++)
{

We continue the current stripe. The letter s[i−1] of the original string is changed to j. That is:

  • the previous i−1 letters have already been transformed and end with j;

  • now add the i-th letter s[i−1], also turning it into j;

  • the total cost will be dp[i−1][j]+cst[i][j].

dp[i][j]=min(dp[i][j],dp[i−1][j]+cst[i][j]);

We start a new stripe of k letters. We assume that at position i a new stripe of exactly k (or more) letters ends, consisting of the letter j. To do this:

  • Take the best transformation of the first (i−k) letters (everything before the new stripe): mn[i−k].

  • • Add the cost of replacing the last k letters (from i−k+1 до i) with j:

ps[i][j]−ps[i−k][j]

If fewer than k characters have been processed, a stripe of this length cannot be formed. Therefore, i≥k.

  if (i >= k) 
    dp[i][j] = min(dp[i][j], ps[i][j] - ps[i - k][j] + mn[i - k]);

After computing all dp[i][j] for a fixed i, we store the best (minimum) value among all j in mn[i].

  mn[i] = min(mn[i], dp[i][j]);
}

Print the answer.

cout << mn[n] << "\n";
Eolymp #1577. So you want to be a 2^n-aire?

The player starts with $1 and must consecutively answer n questions. Before each question, the player can:

  • stop the game and take the money currently in hand;

  • answer the question. If the answer is incorrect, the player leaves the game with nothing. If the answer is correct, the amount of money doubles, and the game proceeds to the next question.

After correctly answering the last question, the player keeps the winnings. The player's goal is to maximize the expected amount of money won.

For each individual question, the player answers correctly with probability p. Assume that p is uniformly distributed over the interval [t,1].

Input. Each line represents a separate test case and contains two numbers: an integer n (1≤n≤30) and a real number t (0≤t≤1). The last line contains two zeros and should not be processed.

Output. For each test case, print on a separate line the maximum expected amount of money the player can win under the optimal strategy. Print the answer with three decimal digits.

Sample input
1 0.5
1 0.3
2 0.6
24 0.25
0 0
Sample output
1.500
1.357
2.560
230.138
Open problem
Solution

Let f(n,a) be the maximum possible expected winnings if the player has to answer n questions and the initial amount is a.

If n=0, the player keeps the initial amount, that is, f(0,a)=a.

The probability of answering a question correctly is p, where t≤p≤1. If the player answers the first question correctly, there remain n−1 questions, and the prize doubles to 2a. With probability 1−p, the player gives an incorrect answer and loses everything. Therefore, the expected winnings after the first question is

p⋅f(n−1,2a)+(1−p)⋅0=p⋅f(n−1,2a)

If this value exceeds the current amount a, it is advantageous to continue the game; otherwise, the player should stop. Thus, the expected winnings after making the decision to continue is

max(a,p⋅f(n−1,2a))

Since the probability p is uniformly distributed over the interval [t;1], then

f(n,a)=1−t1​∫t1​max(a,p⋅f(n−1,2a))dp

If t=1, then the probability of a correct answer equals one, and the player should answer all n questions, obtaining a final prize of 2n.

Example

Let us consider the third test, where n=2,t=0.6. The initial amount a=1.

f(2,1)=0.41​∫0.61​max(1,p⋅f(1,2)) dp,f(1,2)=0.41​∫0.61​max(2,p⋅f(0,4)) dp,f(0,4)=4

Let us compute the value of f(1,2) using f(0,4):

f(1,2)=0.41​∫0.61​max(2,p⋅f(0,4)) dp=2.5⋅∫0.61​max(2,4p) dp=/ taking into account that 4p>2 for 0.6≤p≤1/2.5⋅∫0.61​4p dp=2.5⋅[2p2]0.61​=5⋅(1−0.36)=5⋅0.64=3.2

Let us compute the value of f(2,1) using f(1,2):

f(2,1)=0.41​∫0.61​max(1,p⋅f(1,2)) dp=2.5⋅∫0.61​max(1,3.2p) dp=/ taking into account that 3.2p>1 for 0.6≤p≤1/2.5⋅∫0.61​3.2p dp=2.5⋅[1.6p2]0.61​=4⋅(1−0.36)=4⋅0.64=2.56
Algorithm implementation

The function integral computes the value of the integral

I(a,k)=1−t1​∫t1​max(a,kp)dp

for given real numbers a and k. When t=1, the guessing probability p equals one, so the value of the integral I(a,k) is set to max(a,k).

Below is the region whose area corresponds to the value of the integral ∫t1​max(a,kp)dp:

Let us find the intersection point of the lines y=a and y=kp:

a=kp, hence p=a/k

Let temp=a/k. We consider the value of the integral ∫t1​max(a,kp)dp as the sum of two parts: ∫ttemp​adp + ∫temp1​kpdp. Depending on the position of the point temp relative to t and 1, we compute the value of the integral I(a,k).

  • If t≤temp≤1, then ∫ttemp​adp + ∫temp1​kpdp =

a⋅(temp−t)+k⋅(1−temp⋅temp)/2
  • If temp≤t, then ∫ttemp​adp + ∫temp1​kpdp = ∫t1​kpdp = k⋅(1−t⋅t)/2.

  • If temp>1, then ∫ttemp​adp + ∫temp1​kpdp = ∫t1​adp = a⋅(1−t).

double integral(double a, double k)
{
  double s = 0, temp = a / k;
  if (t == 1) return max(a,k);
  if (temp > 1) return a * (1 - t);
  if (temp >= t) s = a * (temp - t);
  else temp = t;
  s += k * (1 – temp * temp) / 2;
  return s / (1 - t);
}
C++
10 lines
257 bytes

The function f recursively computes the value of f(n,a)={I(a,f(n−1,2a)),n>0a,n=0​.

double f(int n, int a)
{
  if (!n) return a;
  double k = f(n - 1,2 * a);
  return integral(a,k);
}

The main part of the program. Read the input data, and print the value of f(n,1).

while(scanf("%d %lf",&n,&t),n + t)
  printf("%.3lf\n",f(n,1));

1

Коментарі

Завантаження

Секундочку, отримую дані з серверу

Покищо нічого

Будьте першим, хто розпочне обговорення!
Увійти