---
# System prepended metadata

title: Разбор задач 2013 года

---

# Разбор задач 2013 года
Если Вы не знали как решать какую-то задачу и Вам было лень разбираться в коде на Pascal, то это пост специально для Вас.
:::warning
Убедительная просьба не копировать коды и не пересылать их. Помните -- Вы решаете задачи для себя!
:::

## [1. Считалки](https://codeforces.com/group/skz9fIV5Hq/contest/261187/problem/2013_1)
:::spoiler Разбор
:::info
Самым коротким решением в этой задаче является моделирование считалок. Теперь нам нужна структура данных, которая может удалять $k$-ю порядковую статистику. Для этого идеально подойдет *ordered_set*. 

Давайте хранить в *ordered_set* номера всех детей. На очередном ходу будем высчитывать номер игрока, который выйдет из круга. Удалим его из *ordered_set*. Такую несложную операцию повторим $N - 1$ раз. 

Асоптотика: $O(N * log(N))$.
:::
:::spoiler Авторское решение (Pascal)
```pascal
program solution;
var
   left, right, parent : array[1..25000] of longint;
   part		       : array[1..25000] of longint;
   v, node_number      : array[0..25000] of longint;
   root		       : longint;
   n, i, j	       : longint;
   cur		       : longint;
   sum		       : int64;

function init_tree(l,r,p : longint):longint;
var
   t : longint;
begin
   if l>r then init_tree:=0
   else begin
      t := (l+r) div 2;
      left[t] := init_tree(l, t-1, t);
      right[t] := init_tree(t+1, r, t);
      parent[t]:= p;
      node_number[t] := 1;
      if left[t]<>0 then
	 node_number[t] := node_number[t] + node_number[left[t]];
      if right[t]<>0 then
	 node_number[t] := node_number[t] + node_number[right[t]];
      init_tree:=t
   end
end; { init_tree }

procedure forget_node(x, y : longint);
begin
   if parent[x] = 0 then root := y
   else if left[parent[x]] = x then left[parent[x]] := y
   else right[parent[x]] := y;
   if y<>0 then parent[y] := parent[x]
end; { forget_node }

procedure delete_node(x	: longint);
var
   y,z : longint;
begin
   if left[x]=0 then forget_node(x, right[x])
   else if right[x] = 0 then forget_node(x, left[x])
   else begin
      y := right[x];
      while left[y] <> 0 do y := left[y];
      z:=part[y];
      part[y]:=part[x];
      part[x]:=z;
      forget_node(y, right[y]);
      x:=y;
   end;
   x:=parent[x];
   while x<>0 do begin
      node_number[x] := node_number[x] - 1;
      x := parent[x];
   end
end; { delete_node }

function index(i : longint):longint;
var
   t : longint;
begin
   t:=root;
   while i <> node_number[left[t]]+1 do
      if i <= node_number[left[t]] then t:=left[t]
      else begin
	 i:=i-1-node_number[left[t]];
	 t:=right[t]
      end;
   index := t;
end; { index }

begin
   read(n);
   sum:=0;
   for i:=1 to n do begin
      read(v[i]);
      part[i]:=i;
      sum:=sum+v[i];
   end;
   node_number[0]:=0;
   root:=init_tree(1,n,0);
   cur := 0;
   for i := n downto 2 do begin
      cur := (sum + cur) mod i;
      if cur = 0 then j := index(i)
      else begin
	 j:=index(cur);
	 cur := cur - 1
      end;
      sum := sum - v[part[j]];
      delete_node(j)
   end;
   writeln(part[root]);
end.
```
:::
:::spoiler Код (C++, автор: [Zhdun](https://codeforces.com/profile/Zhdun))
```cpp
#include <bits/stdc++.h>
#include <ext/pb_ds/detail/standard_policies.hpp>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace std;
using namespace __gnu_pbds;

template <typename T> using ordered_set = tree <T,null_type,less<T>,rb_tree_tag,tree_order_statistics_node_update>;

int main() {
    int n;
    cin >> n;
    ordered_set<int> all;
    ll sum = 0;
    int a[n + 1];
    for (int i = 1; i <= n; ++i) {
        int x;
        cin >> x;
        all.insert(i);
        sum += x;
        a[i] = x;
    }
    int nach = 1;
    int del;
    int kol;
    int pos;
    while(n > 1) {
        pos = (sum + nach - 1) % n;
        if (!pos) pos = n;
        int x = *all.find_by_order(pos - 1);
        sum -= a[x];
        all.erase(x);
        nach = pos;
        if (n - 1 < nach) nach = 1;
        n--;
    }
    cout << *all.find_by_order(0) << endl;
    return 0;
}
```
:::

## [2. Тренировка (упрощённая версия)](https://codeforces.com/group/skz9fIV5Hq/contest/261187/problem/2013_2)
:::spoiler Разбор
:::info
Считаем динамику $dp_i$ -- количество способов дойти в точку $i$.

Переход: $dp_i = \begin{cases} dp_{i - 2} + dp_{i - 3} \text{, если } i-3 \geq 0 \\ dp_{i - 2} \text{, если } i - 3 < 0 \end{cases}$

Асимптотика: $O(N)$.
:::
:::spoiler Авторское решение (Pascal)
```pascal
program solution;
var 
   n,i : integer;
   f   : array[1..160] of qword;
begin
   readln(n);
   f[1]:=1;
   f[2]:=0;
   f[3]:=1;
   for i:=4 to n do
      f[i]:=f[i-2] + f[i-3];
   writeln(f[n]);
end.
```
:::
:::spoiler Код (C++, автор: [Adamenko](https://codeforces.com/profile/Adamenko))
```cpp
#include <bits/stdc++.h>
using namespace std;

int main() {
    int n;
    cin >> n;
    vector<unsigned long long> dp(n, 0);
    dp[0] = 1;
    dp[1] = 0;
    for (int i = 2; i < n; ++i)
        dp[i] = dp[i - 2] + (i - 3 >= 0 ? dp[i - 3] : 0);
    cout << dp[n - 1] << endl;
    return 0;
}
```
:::

## [3. Две строки](https://codeforces.com/group/skz9fIV5Hq/contest/261187/problem/2013_3)
:::spoiler Разбор
:::info
Давайте переберем начало подстроки в первой строке и будем жадно набирать подпоследовательность во второй строке. 

Асиптотика: $O(N^2)$. 
:::
:::spoiler Авторское решение (Pascal)
```pascal
program solution;
var
   s1, s2  : ansistring;
   i, j, k : integer;
   m, s, f : integer;
begin
   readln(s1);
   readln(s2);
   m:=0;
   s:=1; f:=0;
   for i:=1 to length(s1) do begin
      j:=i;
      k:=1;
      while (j<=length(s1)) and (k<=length(s2)) do begin
	 if (k<=length(s2)) and (s1[j]=s2[k]) then j:=j+1;
	 k:=k+1;
      end;
      j:=j-1;
      if m<j-i+1 then
      begin
	 m:=j-i+1;
	 s:=i;
	 f:=j;
      end;
   end;
   writeln(copy(s1,s,f-s+1));
end.
```
:::
:::spoiler Код (C++, автор: [Adamenko](https://codeforces.com/profile/Adamenko))
```cpp
#include <bits/stdc++.h>
using namespace std;

int main() {
    string s, t;
    cin >> s >> t;
    int n = int(s.size());
    int m = int(t.size());
    int st_ = -1;
    int fn_ = -1;
    int ma = 0;
    for (int z = 0; z < n; ++z) {
        int i = z;
        int j = 0;
        while (i < n && j < m) {
            if (j < m && s[i] == t[j]) i++;
            j++;
        }
        --i;
        if (ma < i - z + 1) ma = i - z + 1, st_ = z, fn_ = i;
    }
    if (st_ == -1) return 0;
    for (int i = st_; i <= fn_; ++i) cout << s[i];
    return 0;
}
```
:::