{"id":"informatyka-2019-maj-matura-rozszerzona/zad/4.3","paper_id":"informatyka-2019-maj-matura-rozszerzona","number":"4.3","points":5,"ptype":"open","subject":"informatyka","category":"matura","year":2019,"month":"maj","level":"rozszerzona","text":"Kontekst - patrz zadanie 4.1.\n\nUwaga: Możesz skorzystać z zależności NWD(a, b, c) = NWD(NWD(a, b), c).\n\nPrzykład:\nDla liczb 3, 7, 4, 6, 10, 2, 5 odpowiedzią jest 4 (pierwsza liczba ciągu), 4 (długość ciągu) i 2 (największy wspólny dzielnik), natomiast dla liczb 5, 70, 28, 42, 98, 1 odpowiedzią jest 70 (pierwsza liczba ciągu), 4 (długość ciągu) i 14 (największy wspólny dzielnik).\n\nOdpowiedź dla pliku przyklad.txt: pierwsza liczba ciągu 90, długość 5, największy wspólny dzielnik 10.\n\nW pliku liczby.txt znajdź najdłuższy ciąg liczb występujących kolejno po sobie i taki, że największy wspólny dzielnik ich wszystkich jest większy od 1 (innymi słowy: istnieje taka liczba całkowita większa od 1, która jest dzielnikiem każdej z tych liczb).\n\nJako odpowiedź podaj wartość pierwszej liczby w takim ciągu, długość ciągu oraz największą liczbę całkowitą, która jest dzielnikiem każdej liczby w tym ciągu. W pliku z danymi jest tylko jeden taki ciąg o największej długości.","answer":null,"answer_text":null,"solution":"## Poprawna odpowiedź\n\n**Najdłuższy ciąg z NWD > 1 w pliku liczby.txt:**\n- **Pierwsza liczba ciągu: 31968**\n- **Długość ciągu: 150**\n- **Największy wspólny dzielnik: 74**\n\n## Sposób 1 - implementacja Python\n\n**Idea:** przeglądamy ciąg od lewej. Utrzymujemy bieżący NWD i długość. Gdy NWD spadnie do 1 - kończymy ciąg, sprawdzamy czy jest najdłuższy, i zaczynamy nowy ciąg od bieżącej liczby. Wykorzystujemy własność: **NWD(a, b, c) = NWD(NWD(a, b), c)**.\n\n```python\nfrom math import gcd\n\nwith open('liczby.txt', encoding='utf-8') as f:\nliczby = [int(linia) for linia in f]\n\nnajdluzszy_start_idx = 0\nnajdluzsza_dlugosc = 1\nnajdluzszy_nwd = liczby[0]\n\nbiezacy_start = 0\nbiezacy_nwd = liczby[0]\n\nfor i in range(1, len(liczby)):\nnowy_nwd = gcd(biezacy_nwd, liczby[i])\nif nowy_nwd > 1:\nbiezacy_nwd = nowy_nwd\ndlugosc = i - biezacy_start + 1\nif dlugosc > najdluzsza_dlugosc:\nnajdluzsza_dlugosc = dlugosc\nnajdluzszy_start_idx = biezacy_start\nnajdluzszy_nwd = biezacy_nwd\nelse:\n# nowy ciąg startuje od liczby[i]\nbiezacy_start = i\nbiezacy_nwd = liczby[i]\n\nprint(f'pierwsza liczba: {liczby[najdluzszy_start_idx]}')\nprint(f'długość: {najdluzsza_dlugosc}')\nprint(f'dzielnik: {najdluzszy_nwd}')\n# pierwsza liczba: 31968\n# długość: 150\n# dzielnik: 74\n\n**Algorytm NWD (Euklides):**\n```python\ndef nwd(a, b):\nwhile b > 0:\na, b = b, a % b\nreturn a\n\n## Sposób 2 - implementacja Pascal\n\n```pascal\nprogram NajdluzszyCiagNWD;\nvar\nf: TextFile;\nliczby: array[1 500] of LongInt;\ni, n: Integer;\nbiezacyStart, biezacyNWD, najStart, najDl, najNWD, nowyNWD, dl: LongInt;\n\nfunction NWD(a, b: LongInt): LongInt;\nvar t: LongInt;\nbegin\nwhile b > 0 do begin t := b; b := a mod b; a := t; end;\nNWD := a;\nend;\n\nbegin\nAssignFile(f, 'liczby.txt');\nReset(f);\nn := 0;\nwhile not Eof(f) do begin Inc(n); ReadLn(f, liczby[n]); end;\nCloseFile(f);\n\nbiezacyStart := 1; biezacyNWD := liczby[1];\nnajStart := 1; najDl := 1; najNWD := liczby[1];\n\nfor i := 2 to n do\nbegin\nnowyNWD := NWD(biezacyNWD, liczby[i]);\nif nowyNWD > 1 then\nbegin\nbiezacyNWD := nowyNWD;\ndl := i - biezacyStart + 1;\nif dl > najDl then\nbegin\nnajDl := dl; najStart := biezacyStart; najNWD := biezacyNWD;\nend;\nend\nelse\nbegin\nbiezacyStart := i; biezacyNWD := liczby[i];\nend;\nend;\n\nWriteLn('pierwsza: ', liczby[najStart]);\nWriteLn('długość: ', najDl);\nWriteLn('dzielnik: ', najNWD);\nend.\n\n## Sposób 3 - implementacja C++\n\n```cpp\n#include <iostream>\n#include <fstream>\n#include <vector>\nusing namespace std;\n\nlong long nwd(long long a, long long b) {\nwhile (b > 0) { long long t = b; b = a % b; a = t; }\nreturn a;\n}\n\nint main() {\nifstream plik(\"liczby.txt\");\nvector<long long> liczby;\nlong long x;\nwhile (plik >> x) liczby.push_back(x);\n\nlong long biezacyNWD = liczby[0], najNWD = liczby[0];\nint biezacyStart = 0, najStart = 0, najDl = 1;\n\nfor (int i = 1; i < (int)liczby.size(); i++) {\nlong long nowy = nwd(biezacyNWD, liczby[i]);\nif (nowy > 1) {\nbiezacyNWD = nowy;\nint dl = i - biezacyStart + 1;\nif (dl > najDl) {\nnajDl = dl;\nnajStart = biezacyStart;\nnajNWD = biezacyNWD;\n}\n} else {\nbiezacyStart = i;\nbiezacyNWD = liczby[i];\n}\n}\n\ncout << \"pierwsza: \" << liczby[najStart] << endl;\ncout << \"długość: \" << najDl << endl;\ncout << \"dzielnik: \" << najNWD << endl;\nreturn 0;\n}\n\n## Weryfikacja na przykładzie\n\nDla `przyklad.txt`: pierwsza 90, długość 5, dzielnik 10. Oznacza, że istnieje ciąg 5 kolejnych liczb (zaczynający się od 90), których wszystkie wartości są wielokrotnościami 10.\n\nDla przykładu z treści: `3, 7, 4, 6, 10, 2, 5`:\n- 3,7 - gcd=1 (koniec ciągu 3 samodzielnie). Start nowego od 7. Ale gcd(7,4)=1 → start od 4.\n- 4,6 → gcd=2. 4,6,10 → gcd=2. 4,6,10,2 → gcd=2. 4,6,10,2,5 → gcd=1. → Ciąg: 4,6,10,2, długość 4, gcd=2 ✓.\n\n## Reference informatyczny - NWD (GCD)\n\n> Reference - Algorytm Euklidesa:\n> ```\n> NWD(a, b):\n> dopóki b > 0\n> a, b = b, a mod b\n> zwróć a\n> ```\n> Złożoność: O(log min(a, b)).\n>\n> Reference - Własności NWD:\n> - NWD(a, b) = NWD(b, a mod b).\n> - NWD(a, 0) = a.\n> - NWD(a, b, c) = NWD(NWD(a, b), c).\n> - NWD(a, b) ≥ 1 zawsze.\n> - NWD(a, b) > 1 ⟺ a i b mają wspólny dzielnik > 1.\n\n## Schemat oceniania CKE\n\n> Klucz CKE (zadanie 4.3, max 5 pkt):\n> - **1 pkt** - pierwsza liczba w ciągu (31968)\n> - **2 pkt** - długość ciągu (150); 1 pkt jeśli różni się o 1 (np. liczenie od 0)\n> - **2 pkt** - wspólny dzielnik (74)\n> - **4 pkt** - za wariant (56536, 149, 74) - wynik z błędem off-by-one\n> - **0 pkt** - błędna albo brak\n\n## Typowe pułapki\n\n- **Resetowanie NWD po nowym elemencie ZAMIAST liczenia od zera** - gdy NWD spadnie do 1, musisz zacząć NOWY ciąg od bieżącej liczby (NIE od następnej).\n- **Aktualizacja długości tylko gdy NWD > 1** - wybór maksymalnej długości musi działać dla najdłuższego ciągu z NWD > 1, NIE każdego okna.\n- **Off-by-one przy długości** - długość = i - start + 1 (gdy indeksowanie od 0).\n- **Pierwsza liczba = `liczby[start]`** - pamiętaj, że pytanie pyta o WARTOŚĆ pierwszej liczby, nie jej indeks.\n- **Złe NWD dla pierwszego ciągu jednoelementowego** - start jako liczba pojedyncza ma NWD = sama ta liczba.\n\n## Złożoność obliczeniowa\n\n- Czytanie pliku: O(n), n = 500.\n- Główna pętla: O(n) iteracji, w każdej NWD: O(log(max)) ≈ 17 operacji dla wartości do 100 000.\n- **Łącznie: O(n · log(max))** ≈ 8500 operacji.\n- Pamięć: O(n) na tablicę liczb (lub O(1) gdy czytamy streaming).","image":null,"solution_image":null,"topics":null,"page_from":null,"source":"maturazai","answer_source":null,"answer_text_source":null,"solution_source":"maturazai","text_source":"maturazai","source_label":"Informatyka · Matura · maj 2019 (rozszerzona)","subject_label":"Informatyka","category_label":"Matura","text_html":"<p>Kontekst - patrz zadanie 4.1.</p>\n<p>Uwaga: Możesz skorzystać z zależności NWD(a, b, c) = NWD(NWD(a, b), c).</p>\n<p>Przykład:<br>Dla liczb 3, 7, 4, 6, 10, 2, 5 odpowiedzią jest 4 (pierwsza liczba ciągu), 4 (długość ciągu) i 2 (największy wspólny dzielnik), natomiast dla liczb 5, 70, 28, 42, 98, 1 odpowiedzią jest 70 (pierwsza liczba ciągu), 4 (długość ciągu) i 14 (największy wspólny dzielnik).</p>\n<p>Odpowiedź dla pliku przyklad.txt: pierwsza liczba ciągu 90, długość 5, największy wspólny dzielnik 10.</p>\n<p>W pliku liczby.txt znajdź najdłuższy ciąg liczb występujących kolejno po sobie i taki, że największy wspólny dzielnik ich wszystkich jest większy od 1 (innymi słowy: istnieje taka liczba całkowita większa od 1, która jest dzielnikiem każdej z tych liczb).</p>\n<p>Jako odpowiedź podaj wartość pierwszej liczby w takim ciągu, długość ciągu oraz największą liczbę całkowitą, która jest dzielnikiem każdej liczby w tym ciągu. W pliku z danymi jest tylko jeden taki ciąg o największej długości.</p>","solutions":[{"source":"maturazai","label":"maturazai.pl (AI)","kind":"text","html":"<h4>Poprawna odpowiedź</h4>\n<p><strong>Najdłuższy ciąg z NWD &gt; 1 w pliku liczby.txt:</strong></p>\n<ul><li><strong>Pierwsza liczba ciągu: 31968</strong></li><li><strong>Długość ciągu: 150</strong></li><li><strong>Największy wspólny dzielnik: 74</strong></li></ul>\n<h4>Sposób 1 - implementacja Python</h4>\n<p><strong>Idea:</strong> przeglądamy ciąg od lewej. Utrzymujemy bieżący NWD i długość. Gdy NWD spadnie do 1 - kończymy ciąg, sprawdzamy czy jest najdłuższy, i zaczynamy nowy ciąg od bieżącej liczby. Wykorzystujemy własność: <strong>NWD(a, b, c) = NWD(NWD(a, b), c)</strong>.</p>\n<p>```python<br>from math import gcd</p>\n<p>with open(&#x27;liczby.txt&#x27;, encoding=&#x27;utf-8&#x27;) as f:<br>liczby = [int(linia) for linia in f]</p>\n<p>najdluzszy_start_idx = 0<br>najdluzsza_dlugosc = 1<br>najdluzszy_nwd = liczby[0]</p>\n<p>biezacy_start = 0<br>biezacy_nwd = liczby[0]</p>\n<p>for i in range(1, len(liczby)):<br>nowy_nwd = gcd(biezacy_nwd, liczby[i])<br>if nowy_nwd &gt; 1:<br>biezacy_nwd = nowy_nwd<br>dlugosc = i - biezacy_start + 1<br>if dlugosc &gt; najdluzsza_dlugosc:<br>najdluzsza_dlugosc = dlugosc<br>najdluzszy_start_idx = biezacy_start<br>najdluzszy_nwd = biezacy_nwd<br>else:</p>\n<h3>nowy ciąg startuje od liczby[i]</h3>\n<p>biezacy_start = i<br>biezacy_nwd = liczby[i]</p>\n<p>print(f&#x27;pierwsza liczba: {liczby[najdluzszy_start_idx]}&#x27;)<br>print(f&#x27;długość: {najdluzsza_dlugosc}&#x27;)<br>print(f&#x27;dzielnik: {najdluzszy_nwd}&#x27;)</p>\n<h3>pierwsza liczba: 31968</h3>\n<h3>długość: 150</h3>\n<h3>dzielnik: 74</h3>\n<p><strong>Algorytm NWD (Euklides):</strong><br>```python<br>def nwd(a, b):<br>while b &gt; 0:<br>a, b = b, a % b<br>return a</p>\n<h4>Sposób 2 - implementacja Pascal</h4>\n<p>```pascal<br>program NajdluzszyCiagNWD;<br>var<br>f: TextFile;<br>liczby: array[1 500] of LongInt;<br>i, n: Integer;<br>biezacyStart, biezacyNWD, najStart, najDl, najNWD, nowyNWD, dl: LongInt;</p>\n<p>function NWD(a, b: LongInt): LongInt;<br>var t: LongInt;<br>begin<br>while b &gt; 0 do begin t := b; b := a mod b; a := t; end;<br>NWD := a;<br>end;</p>\n<p>begin<br>AssignFile(f, &#x27;liczby.txt&#x27;);<br>Reset(f);<br>n := 0;<br>while not Eof(f) do begin Inc(n); ReadLn(f, liczby[n]); end;<br>CloseFile(f);</p>\n<p>biezacyStart := 1; biezacyNWD := liczby[1];<br>najStart := 1; najDl := 1; najNWD := liczby[1];</p>\n<p>for i := 2 to n do<br>begin<br>nowyNWD := NWD(biezacyNWD, liczby[i]);<br>if nowyNWD &gt; 1 then<br>begin<br>biezacyNWD := nowyNWD;<br>dl := i - biezacyStart + 1;<br>if dl &gt; najDl then<br>begin<br>najDl := dl; najStart := biezacyStart; najNWD := biezacyNWD;<br>end;<br>end<br>else<br>begin<br>biezacyStart := i; biezacyNWD := liczby[i];<br>end;<br>end;</p>\n<p>WriteLn(&#x27;pierwsza: &#x27;, liczby[najStart]);<br>WriteLn(&#x27;długość: &#x27;, najDl);<br>WriteLn(&#x27;dzielnik: &#x27;, najNWD);<br>end.</p>\n<h4>Sposób 3 - implementacja C++</h4>\n<p>```cpp<br>#include &lt;iostream&gt;<br>#include &lt;fstream&gt;<br>#include &lt;vector&gt;<br>using namespace std;</p>\n<p>long long nwd(long long a, long long b) {<br>while (b &gt; 0) { long long t = b; b = a % b; a = t; }<br>return a;<br>}</p>\n<p>int main() {<br>ifstream plik(&quot;liczby.txt&quot;);<br>vector&lt;long long&gt; liczby;<br>long long x;<br>while (plik &gt;&gt; x) liczby.push_back(x);</p>\n<p>long long biezacyNWD = liczby[0], najNWD = liczby[0];<br>int biezacyStart = 0, najStart = 0, najDl = 1;</p>\n<p>for (int i = 1; i &lt; (int)liczby.size(); i++) {<br>long long nowy = nwd(biezacyNWD, liczby[i]);<br>if (nowy &gt; 1) {<br>biezacyNWD = nowy;<br>int dl = i - biezacyStart + 1;<br>if (dl &gt; najDl) {<br>najDl = dl;<br>najStart = biezacyStart;<br>najNWD = biezacyNWD;<br>}<br>} else {<br>biezacyStart = i;<br>biezacyNWD = liczby[i];<br>}<br>}</p>\n<p>cout &lt;&lt; &quot;pierwsza: &quot; &lt;&lt; liczby[najStart] &lt;&lt; endl;<br>cout &lt;&lt; &quot;długość: &quot; &lt;&lt; najDl &lt;&lt; endl;<br>cout &lt;&lt; &quot;dzielnik: &quot; &lt;&lt; najNWD &lt;&lt; endl;<br>return 0;<br>}</p>\n<h4>Weryfikacja na przykładzie</h4>\n<p>Dla <code>przyklad.txt</code>: pierwsza 90, długość 5, dzielnik 10. Oznacza, że istnieje ciąg 5 kolejnych liczb (zaczynający się od 90), których wszystkie wartości są wielokrotnościami 10.</p>\n<p>Dla przykładu z treści: <code>3, 7, 4, 6, 10, 2, 5</code>:</p>\n<ul><li>3,7 - gcd=1 (koniec ciągu 3 samodzielnie). Start nowego od 7. Ale gcd(7,4)=1 → start od 4.</li><li>4,6 → gcd=2. 4,6,10 → gcd=2. 4,6,10,2 → gcd=2. 4,6,10,2,5 → gcd=1. → Ciąg: 4,6,10,2, długość 4, gcd=2 ✓.</li></ul>\n<h4>Reference informatyczny - NWD (GCD)</h4>\n<blockquote>Reference - Algorytm Euklidesa:<br>```<br>NWD(a, b):<br>dopóki b &gt; 0<br>a, b = b, a mod b<br>zwróć a<br>```<br>Złożoność: O(log min(a, b)).<br><br>Reference - Własności NWD:<br>- NWD(a, b) = NWD(b, a mod b).<br>- NWD(a, 0) = a.<br>- NWD(a, b, c) = NWD(NWD(a, b), c).<br>- NWD(a, b) ≥ 1 zawsze.<br>- NWD(a, b) &gt; 1 ⟺ a i b mają wspólny dzielnik &gt; 1.</blockquote>\n<h4>Schemat oceniania CKE</h4>\n<blockquote>Klucz CKE (zadanie 4.3, max 5 pkt):<br>- <strong>1 pkt</strong> - pierwsza liczba w ciągu (31968)<br>- <strong>2 pkt</strong> - długość ciągu (150); 1 pkt jeśli różni się o 1 (np. liczenie od 0)<br>- <strong>2 pkt</strong> - wspólny dzielnik (74)<br>- <strong>4 pkt</strong> - za wariant (56536, 149, 74) - wynik z błędem off-by-one<br>- <strong>0 pkt</strong> - błędna albo brak</blockquote>\n<h4>Typowe pułapki</h4>\n<ul><li><strong>Resetowanie NWD po nowym elemencie ZAMIAST liczenia od zera</strong> - gdy NWD spadnie do 1, musisz zacząć NOWY ciąg od bieżącej liczby (NIE od następnej).</li><li><strong>Aktualizacja długości tylko gdy NWD &gt; 1</strong> - wybór maksymalnej długości musi działać dla najdłuższego ciągu z NWD &gt; 1, NIE każdego okna.</li><li><strong>Off-by-one przy długości</strong> - długość = i - start + 1 (gdy indeksowanie od 0).</li><li><strong>Pierwsza liczba = <code>liczby[start]</code></strong> - pamiętaj, że pytanie pyta o WARTOŚĆ pierwszej liczby, nie jej indeks.</li><li><strong>Złe NWD dla pierwszego ciągu jednoelementowego</strong> - start jako liczba pojedyncza ma NWD = sama ta liczba.</li></ul>\n<h4>Złożoność obliczeniowa</h4>\n<ul><li>Czytanie pliku: O(n), n = 500.</li><li>Główna pętla: O(n) iteracji, w każdej NWD: O(log(max)) ≈ 17 operacji dla wartości do 100 000.</li><li><strong>Łącznie: O(n · log(max))</strong> ≈ 8500 operacji.</li><li>Pamięć: O(n) na tablicę liczb (lub O(1) gdy czytamy streaming).</li></ul>"}]}