# Разбор задач 2017 года
Если Вы не знали как решать какую-то задачу и Вам было лень разбираться в коде на Pascal, то это пост специально для Вас.
:::warning
Убедительная просьба не копировать коды и не пересылать их. Помните -- Вы решаете задачи для себя!
:::
## [1. Самый маленький огород](https://codeforces.com/group/skz9fIV5Hq/contest/261187/problem/2017_1)
:::spoiler Разбор
:::info
$S_{трапеции} = \frac{a + b}{2} * h = (a + b) * \frac{h}{2}$.
По условию $h = 50$, тогда ответ равен $min(L_i + L_{i - 1}) * 25$ для всех $i$ от $2$ до $n$.
Асимптотика: $O(N)$.
:::
:::spoiler Авторское решение (Pascal)
```pascal
var
n,i:longint;
a,b,s,ms:longint;
begin
read(n);
read(a,b);
ms:=(a+b)*25;
while not seekeof(input) do begin
a:=b;
read(b);
s:=(a+b)*25;
if s < ms then ms := s;
end;
writeln(ms);
end.
```
:::
:::spoiler Код (C++, автор: [gamora](https://codeforces.com/profile/gamora))
```cpp
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
long long last;
cin >> last;
long long ot = 1e18;
for (int i = 0; i < n; i++) {
long long x;
cin >> x;
ot = min((last + x) * 25, ot);
last = x;
}
cout << ot << endl;
return 0;
}
```
:::
## [2. Выбор костюма](https://codeforces.com/group/skz9fIV5Hq/contest/261187/problem/2017_2)
:::spoiler Разбор
:::info
Давайте для каждого $a_i$ посчитаем максимальное значение ($mx\_b[a_i]$) $b_i$ и их количество $kol[a_i]$. Заметим, что немаксимальные значения $b_i$ для каждого из $a_i$ не входят в ответ.
Теперь пройдемся по всем $a$ с конца и будем хранить максимальное значение ($mx$) среди всех $mx\_b[i]$ ($a \leq i \leq 1000$). Если мы обновляем значение $mx$, то мы точно сохраним эти платья. Другие платья удалятся, т.к мы идем с конца и значение текущего $mx > mx\_b[a]$.
Асимптотика: $O(N)$.
:::
:::spoiler Авторское решение (Pascal)
```pascal
var
mb:array[1..1000] of integer;
mbk:array[1..1000] of integer;
n,i,r:longint;
a,b,maxb:integer;
begin
for i:=1 to 1000 do begin
mb[i]:=0;
mbk[i]:=0;
end;
read(n);
for i:=1 to n do begin
read(a,b);
if b > mb[a] then begin
mb[a]:=b;
mbk[a]:=1;
end
else if b = mb[a] then mbk[a]:=mbk[a]+1;
end;
r:=0;
maxb:=0;
for i:=1000 downto 1 do
if mb[i]>maxb then begin
r:=r+mbk[i];
maxb:=mb[i];
end;
writeln(r);
end.
```
:::
:::spoiler Код (C++, автор: [Adamenko](https://codeforces.com/profile/Adamenko))
```cpp
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
map<int, int> mp;
map<int, int> kol;
for (int i = 0; i < n; ++i) {
int a, b;
cin >> a >> b;
if (mp[a] < b) mp[a] = b, kol[a] = 1;
else if (mp[a] == b) kol[a]++;
}
int ans = 0;
int ma = 0;
for (int i = 1000; i >= 0; --i)
if (mp[i] > ma) ma = mp[i], ans += kol[i];
cout << ans << endl;
return 0;
}
```
:::
## [3. Четные цифры](https://codeforces.com/group/skz9fIV5Hq/contest/261187/problem/2017_3)
:::spoiler Разбор
:::info
Давайте напишем ДП по цифрам: $dp[префикс][флажок] = ответ$.
Давайте напишем наше $dp$ с 3-мя флажками.
$i$ -- 0-индексация.
$dp[i][0]$ -- количество четных цифр для всех чисел длины $i + 1$. Все числа строго меньше нашего префикса длины $i$.
$dp[i][1]$ -- количество четных цифр для всех чисел длины $i + 1$. Все числа равны нашему префиксу длины $i$.
$dp[i][2]$ -- количество четных цифр для всех чисел длины $i + 1$. Все числа строго больше нашего префикса длины $i$.
Самое главное в этой задаче -- заметить, что когда мы добавляем очередную
четную цифру, то ответ увеличивается не на $1$, а на количество чисел, которые
соответсвуют $[префикс][флажок]$.
Тогда нам нужно поддерживать количество чисел, которые имеют длину нашего
текущего префикса и, взависимости от флажка, либо $<$, либо $=$, либо $>$.
Для тренировки мы можем считать такую матрицу с помощью ДП по цифрам.
Асимптотика: $O(len * 10)$, где $len$ -- длина исходного числа.
:::
:::spoiler Авторское решение (Pascal)
```pascal
var
zn, bl: array[0..11] of int64;
procedure initc;
var
i :integer;
pw :int64;
begin
zn[0]:=0;
bl[0]:=0;
pw:=1;
for i:=1 to 11 do begin
zn[i]:=4*pw+9*bl[i-1];
bl[i]:=5*pw+10*bl[i-1];
pw:=pw*10;
end;
end;
function count(x : longint):int64;
var
pw:int64;
k:int64;
n,d:integer;
begin
pw:=1;
n:=1;
k:=0;
while x >= 10*pw do begin
k:=k+zn[n];
n:=n+1;
pw:=pw*10;
end;
d:=x div pw;
x:=x-d*pw;
k:=k+(d-1)*bl[n-1]+((d-1) div 2 )*pw;
if (d>0) and (d mod 2 = 0) then k := k+x+1;
n:=n-1;
pw:=pw div 10;
while n > 0 do begin
d:=x div pw;
x:=x-d*pw;
k:=k+d*bl[n-1]+((d+1) div 2 )*pw;
if d mod 2 = 0 then k := k+x+1;
n:=n-1;
pw:=pw div 10;
end;
count:=k;
end;
var
a,b : longint;
ka,kb : int64;
f : text;
begin
initc;
read(a,b);
ka:=count(a-1);
kb:=count(b);
writeln(kb-ka);
end.
```
:::
:::spoiler Код (C++, автор: [Adamenko](https://codeforces.com/profile/Adamenko))
```cpp
#include <bits/stdc++.h>
#define ll long long
#define pb push_back
#pragma GCC optimize("Ofast")
using namespace std;
ll dp[10][3];
int kol[10][3];
ll solve(int val){
if (!val)return 0;
for (int i = 0;i < 10; ++i){
for (int j = 0;j < 3; ++j){
dp[i][j] = 0;
kol[i][j] = 0;
}
}
vector < int > a;
while(val){
a.pb(val % 10);
val /= 10;
}
reverse(a.begin(), a.end());
int n = a.size();
for (int i = 1;i <= 9; ++i){
if (i < a[0])dp[0][0] += !(i % 2), kol[0][0]++;
else if (i == a[0])dp[0][1] += !(i % 2), kol[0][1]++;
else dp[0][2] += !(i % 2), kol[0][2]++;
}
for (int i = 1;i < n; ++i){
for (int c = 0;c < 10; ++c){
int need = !(c % 2);
kol[i][0] += kol[i - 1][0];
kol[i][2] += kol[i - 1][2];
dp[i][0] += dp[i - 1][0] + need * kol[i - 1][0];
dp[i][2] += dp[i - 1][2] + need * kol[i - 1][2];
if (c < a[i]){
kol[i][0] += kol[i - 1][1];
dp[i][0] += dp[i - 1][1] + need * kol[i - 1][1];
}else if (c == a[i]){
kol[i][1] += kol[i - 1][1];
dp[i][1] += dp[i - 1][1] + need * kol[i - 1][1];
}else{
kol[i][2] += kol[i - 1][1];
dp[i][2] += dp[i - 1][1] + need * kol[i - 1][1];
}
}
}
ll ans = 0;
for (int i = 0;i < n; ++i){
if (i == n - 1)ans += dp[i][0] + dp[i][1];
else ans += dp[i][0] + dp[i][1] + dp[i][2];
}
return ans;
}
int32_t main() {
int a, b;
cin >> a >> b;
cout << solve(b) - solve(a - 1) << endl;
return 0;
}
```
:::
## [4. Неинтересный лабиринт](https://codeforces.com/group/skz9fIV5Hq/contest/261187/problem/2017_4)
:::spoiler Разбор
:::info
Давайте посчитаем $dp_i$ -- минимальное количество энергии, которая потребуется, чтобы дойти от $i$ до $n$. Считаем динамику с конца.
Переход: $dp_i = min(dp_{i + 1} + a_{i + 1}, dp_{i + 2} + a_{i + 2})$
Асмптотика решения: $O(N)$.
:::
:::spoiler Авторское решение (Pascal)
```pascal
var
n,i:longint;
a:array[1..1000000]of longint;
r:array[0..1000000]of int64;
begin
read(n);
for i:=1 to n do
read(a[i]);
r[n]:=0;
r[n-1]:=a[n];
for i:=n-2 downto 1 do begin
if r[i+1]+a[i+1] < r[i+2]+a[i+2] then r[i]:=a[i+1]+r[i+1]
else r[i]:=a[i+2]+r[i+2];
if r[i]<0 then r[i]:=0;
end;
writeln(r[1]);
end.
```
:::
:::spoiler Код (C++, автор: [Adamenko](https://codeforces.com/profile/Adamenko))
```cpp
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
long long dp[n+1];
int a[n+1];
for (int i = 1; i <= n; ++i)
cin >> a[i];
dp[n] = 0;
dp[n-1] = a[n];
for (int i = n-2; i >= 1; --i) {
dp[i] = min(dp[i+1] + a[i+1], dp[i+2] + a[i+2]);
if (dp[i] < 0)
dp[i] = 0;
}
cout << dp[1] << endl;
return 0;
}
```
:::