Zadanie
Táto úloha je programátorská. Ako svoje riešenie odovzdaj program vo svojom obľúbenom jazyku a automaticky sa dozvieš koľko si dostal/a bodov. Ak si takýto typ úloh ešte nikdy neriešil/a skús sa pozrieť ako by mal vyzerať ideálny program. Ak zatiaľ programovať nevieš, ale chcel/a by si vedieť možeš skúsiť náš python tutoriál.
Ak máte akékoľvek otázky ohľadom tejto úlohy, napíšte Klaudi na [email protected]
Miško kúpil veľa jahodových džúsikov a keďže je štedrý, chce sa podeliť s Klaudi. Miško býva veľmi smädný a preto potrebuje džúsikov viac ako Klaudi. Miško a Klaudi zistili, že spôsobov, ako si džúsiky rozdeliť je aspoň 2 a keďže sú zaneprázdnení pitím džúsikov, tak túto úlohu nechali na vás.
Úloha
Vašou úlohou je zistiť, koľkými spôsobmi si vedia rozdeliť džúsiky, ak každý musí dostať aspoň jeden džúsik a Miško musí dostať džúsikov viac ako Klaudi. Všetky džúsiky sú rovnaké a navzájom zameniteľné. Ak si ich nevedia rozdeliť tak, aby boli splnené tieto podmienky tak počet možností je \(0\).
Formát vstupu
Na jedinom riadku vstupu je jedno kladné celé číslo \(d\) - počet džúsikov.
Formát výstupu
Vypíšte jedno číslo: počet možností, koľkými si Miško a Klaudi vedia džúsiky rozdeliť.
Hodnotenie
Existuje 5 sád vstupov. Pre prvú sadu platí, že \(d \leq 100\). Pre druhú a tretiu sadu platí, že \(d \leq 10^6\). Pre posledné dve sady platí, že \(d \leq 10^9\).
Príklad
Input:
6
Output:
2
Máme 6 džúsikov a vieme ich rozdeliť tak, že Klaudi dostane 1 a Miško 5 alebo Klaudi dostane 2 a Miško 4
Input:
2
Output:
0
Máme 2 džúsiky. Nevieme ich rozdeliť tak, aby každý dostal aspoň jeden a Miško mal viac ako Klaudi
Input:
13
Output:
6
Input:
373
Output:
186
Našou úlohou bolo zistiť koľkými spôsobmi si viedia miško a Klaudi rozdeliť džúsiky tak, aby platili 2 podmienky: obidvaja musia mať aspoň jededn džúsik a Miško ich musí mať viac.
Prvé riešenie
Máme teda \(d\) džúsikov. Označme \(m\) počet džúsikov, ktoré dostane Miško. Mohli by sme skúsiť všetkky možnosti na číslo \(m\). Vieme, že \(1 \leq m \leq d\) Keďže Miško musí dostať aspoň jeden džúsik a nevie ich dostať viac ako \(d\) (všetky). Klaudi by potom dostala \(d - m\) džúsikov. Treba ešte otestovať, či Klaudi dostala aspoň \(1\) džúsik a či ich má Miško viac. Môžeme si ešte všimnúť, že ak by Miško dostal \(d\) džúsikov, pre Klaudi by žiaden nezostal. A keď Miško dostane menaj ako \(d\) džúsikov, Klaudi určite dostane aspoň jeden. Potom to ani nemusíme v programe testovať.
Program by mohol vyzerať napríklad takto:
# načítame počet džúsikov
= int(input())
d
# počet vyhovujúcich možností na začiatku nastavíme na 0
= 0
možnosti
# prejdeme všetky možnosti na m
for m in range(1, d):
# Klaudi dostane džúsikov
= d - m
k
# ak Miško má viac džúsikov ako Klaudi
if m > k:
# vyhovujúca možnosť, zväčšíme ich počet
+= 1
možnosti
# vypíšeme výsledný počet možností
print(možnosti)
Časová zložitosť tohto programu je \(O(d)\), keďže v cykle skúšame každú možnosť na \(m\), a tých je až (približne) \(d\). Pamäťová zložitosť je \(O(1)\) keďže si v každom momente pamätáme len niekoľko čísel.
Rýchlejšie riešenie
Pozrime sa na to, koľko najmenej džúšikov môže Miško dostať tak, aby mal viac ako Klaudi.
Ak by bol počet džúsikov párny, najmenej džúsikov, koľko by Miško dostal je \(\frac{d}{2} + 1\). Potom by Klaudi dostala \(\frac{d}{2} - 1\), čo je menej. Ak by Miško dostal čo i len o jeden džúsik menej, už by mali s Klaudi rovnako.
Ak by bol počet džúsikov nepárny, najmenej džúsikov, koľko by Miško dostal je \(\frac{d-1}{2} + 1\) (\(d-1\) je párne čislo). Potom by Klaudi dostala \(\frac{d-1}{2}\), čo je menej. Ak by Miško dostal čo i len o jeden džúsik menej, už by Klaudi mala viac.
Zistili sme, koľko najmenej môže Miško dostať džúsikov. Vieme, že Miško môže dostať najviac \(d-1\) džúsikov tak aby Klaudi dostala aspoň jeden. Každý počet džúsikov medzi tým je tiež správna (vyhovujúca) možnosť. Keď vieme koľko najviac a koľko najmenej džúsikov môže Miško dostať, ľahko zistíme počet možností. Je to \(najviac - najmenej + 1\).
Program by vyzeral takto:
# načítame počet džúsikov
= int(input())
d
# Ak d je párne
if d % 2 == 0:
= d // 2 + 1
najmenej
# inak je d nepárne
else:
= (d - 1) // 2 + 1
najmenej
= d - 1
najviac
= najviac - najmenej + 1
možnosti
# vypíšeme výsledný počet možností
print(možnosti)
Časová a pamäťová zložitosť
Časová zložitosť tohto programu je O(1). Robíme len niekoľko operácií s číslami. To znamená že náš program bude bežať približne rovnako dlho aj pre malé hodnoty \(d\), aj pre veľké. To napríklad u predošlého riešenia neplatilo. Pamäťová zložitosť je \(O(1)\), keďže si v každom momente pamätáme len niekoľko čísel.
Triky na skrátenie programu
Vo všeobecnosti neplatí, že kratší program je lepší. Je to skôr
naopak, kratší menej prehľadný program býva horší. Ukážeme si však ako
by sa dalo predošlé riešenie ešte skrátiť. Využijeme vlastnosť
programovacieho jazyku, a to takzvané celočíselné delenie. V Pythone sa
značí //
a dáva nám výsledok po delení bezo zvyšku. Ak teda
spravíme napr. 5 // 2
výjde nám výsledok \(2\). Síce \(5
\div 2 = 2 zv. 1\), zvyšok sa ale pri tejto operácií zahodí.
To vieme využiť vo svoj prospech. Nebudeme musieť rozlišovať medzi prípadom párneho a nepárneho \(d\). Náš program by sme potom vedeli napísať dokonca na dva riadky:
= int(input())
d print((d - 1) - (d // 2 + 1) + 1)
Diskusia
Tu môžte voľne diskutovať o riešení, deliť sa o svoje kusy kódu a podobne.
Pre pridávanie komentárov sa musíš prihlásiť.