{"id":"informatyka-2019-maj-matura-rozszerzona/zad/4.2","paper_id":"informatyka-2019-maj-matura-rozszerzona","number":"4.2","points":4,"ptype":"open","subject":"informatyka","category":"matura","year":2019,"month":"maj","level":"rozszerzona","text":"Kontekst - patrz zadanie 4.1.\n\nSilnią liczby naturalnej k większej od 0 nazywamy wartość iloczynu 1·2 k i oznaczamy przez k!. Przyjmujemy, że 0!=1. Zatem mamy:\n- 0! = 1\n- 1! = 1\n- 2! = 1·2 = 2\n- 3! = 1·2·3 = 6\n- 4! = 1·2·3·4 = 24 itd.\n\nDowolną liczbę naturalną możemy rozbić na cyfry, a następnie policzyć sumę silni jej cyfr. Na przykład dla liczby 343 mamy 3! + 4! + 3! = 6 + 24 + 6 = 36.\n\nW pliku przyklad.txt znajduje się jedna taka liczba: 145 (1!+4!+5! =1+24+120 =145).\n\nPodaj, w kolejności ich występowania w pliku liczby.txt, wszystkie liczby, które są równe sumie silni swoich cyfr.","answer":null,"answer_text":null,"solution":"## Poprawna odpowiedź\n\n**Liczby z pliku liczby.txt równe sumie silni swoich cyfr (w kolejności występowania):**\n\n2\n145\n1\n40585\n\n**Te liczby to tzw. \"factorions\" - w dziesiętnym wszystkich jest dokładnie 4: 1, 2, 145, 40585.**\n\n## Sposób 1 - implementacja Python\n\n```python\n# Precomputed silnie 0! 9!\nsilnie = [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880]\n\ndef suma_silni_cyfr(n):\ns = 0\nif n == 0:\nreturn 1 # 0! = 1\nwhile n > 0:\ns += silnie[n % 10]\nn //= 10\nreturn s\n\nwyniki = []\nwith open('liczby.txt', encoding='utf-8') as f:\nfor linia in f:\nn = int(linia.strip())\nif suma_silni_cyfr(n) == n:\nwyniki.append(n)\n\nfor w in wyniki:\nprint(w)\n# 2\n# 145\n# 1\n# 40585\n\n**Weryfikacja:**\n- 1: 1! = 1 ✓\n- 2: 2! = 2 ✓\n- 145: 1! + 4! + 5! = 1 + 24 + 120 = **145** ✓\n- 40585: 4! + 0! + 5! + 8! + 5! = 24 + 1 + 120 + 40320 + 120 = **40585** ✓\n\n## Sposób 2 - implementacja Pascal\n\n```pascal\nprogram SumaSilniCyfr;\nvar\nf: TextFile;\nn, m, suma, cyfra, i: LongInt;\nsilnie: array[0 9] of LongInt;\nbegin\nsilnie[0] := 1;\nfor i := 1 to 9 do silnie[i] := silnie[i-1] * i;\nAssignFile(f, 'liczby.txt');\nReset(f);\nwhile not Eof(f) do\nbegin\nReadLn(f, n);\nm := n; suma := 0;\nif m = 0 then suma := 1\nelse while m > 0 do\nbegin\ncyfra := m mod 10;\nsuma := suma + silnie[cyfra];\nm := m div 10;\nend;\nif suma = n then WriteLn(n);\nend;\nCloseFile(f);\nend.\n\n## Sposób 3 - implementacja C++\n\n```cpp\n#include <iostream>\n#include <fstream>\nusing namespace std;\n\nint silnie[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880};\n\nlong long sumaSilniCyfr(long long n) {\nif (n == 0) return 1;\nlong long s = 0;\nwhile (n > 0) {\ns += silnie[n % 10];\nn /= 10;\n}\nreturn s;\n}\n\nint main() {\nifstream plik(\"liczby.txt\");\nlong long n;\nwhile (plik >> n) {\nif (sumaSilniCyfr(n) == n) cout << n << endl;\n}\nreturn 0;\n}\n\n## Reference informatyczny - wydobywanie cyfr liczby\n\n> Reference - Algorytm na rozkład liczby na cyfry:\n> ```\n> dopóki n > 0\n> cyfra ← n mod 10\n> n ← n div 10\n> ```\n> Złożoność: O(log₁₀(n)) - liczba cyfr.\n>\n> Reference - Silnia:\n> - 0! = 1, n! = n · (n-1)! dla n > 0.\n> - Rosnie szybko: 10! = 3 628 800, 12! przekracza 32-bit int.\n> - Pre-kompute: tablica silni[0 9] = [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880].\n>\n> Reference - Factoriony:\n> - W dziesiętnym SĄ TYLKO 4 factoriony: 1, 2, 145, 40585. Udowodniono, że więcej nie istnieje.\n\n## Schemat oceniania CKE\n\n> Klucz CKE (zadanie 4.2, max 4 pkt):\n> - **4 pkt** - wszystkie 4 liczby (2, 145, 1, 40585) w prawidłowej kolejności\n> - **1 pkt** za każdą poprawną liczbę w wyniku\n> - **0 pkt** - błędna albo brak\n\n## Typowe pułapki\n\n- **Pominięcie 0! = 1** - bez tego dla liczby 40585 wynik byłby 23+1+120+40320+120 = 40584 (lub mocno błędny).\n- **Kolejność w wyniku** - musi być w kolejności pojawiania się w pliku liczby.txt (nie alfabetycznie/numerycznie).\n- **Złe wpisanie tablicy silni** - najczęstszy błąd: pomylenie 5! = 120 z 6! = 720.\n- **Overflow w Pascal/C++** - 9! = 362880 mieści się w 32-bit int, ale uważać dla wielocyfrowych liczb.\n- **Brak warunku zatrzymania pętli** - gdy n=0 (liczba 0 nie pojawi się w danych, bo zakres 1-100000).\n\n## Złożoność obliczeniowa\n\n- Wczytanie pliku: O(n) - 500 wierszy.\n- Obliczenie sumy silni cyfr: O(log n) ≈ 6 operacji (max 6 cyfr).\n- Łącznie: **O(n · log(max))** ≈ 3000 operacji - błyskawicznie.\n- Pamięć: O(1) (tablica silni stała).","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>Silnią liczby naturalnej k większej od 0 nazywamy wartość iloczynu 1·2 k i oznaczamy przez k!. Przyjmujemy, że 0!=1. Zatem mamy:</p>\n<ul><li>0! = 1</li><li>1! = 1</li><li>2! = 1·2 = 2</li><li>3! = 1·2·3 = 6</li><li>4! = 1·2·3·4 = 24 itd.</li></ul>\n<p>Dowolną liczbę naturalną możemy rozbić na cyfry, a następnie policzyć sumę silni jej cyfr. Na przykład dla liczby 343 mamy 3! + 4! + 3! = 6 + 24 + 6 = 36.</p>\n<p>W pliku przyklad.txt znajduje się jedna taka liczba: 145 (1!+4!+5! =1+24+120 =145).</p>\n<p>Podaj, w kolejności ich występowania w pliku liczby.txt, wszystkie liczby, które są równe sumie silni swoich cyfr.</p>","solutions":[{"source":"maturazai","label":"maturazai.pl (AI)","kind":"text","html":"<h4>Poprawna odpowiedź</h4>\n<p><strong>Liczby z pliku liczby.txt równe sumie silni swoich cyfr (w kolejności występowania):</strong></p>\n<p>2<br>145<br>1<br>40585</p>\n<p><strong>Te liczby to tzw. &quot;factorions&quot; - w dziesiętnym wszystkich jest dokładnie 4: 1, 2, 145, 40585.</strong></p>\n<h4>Sposób 1 - implementacja Python</h4>\n<p>```python</p>\n<h3>Precomputed silnie 0! 9!</h3>\n<p>silnie = [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880]</p>\n<p>def suma_silni_cyfr(n):<br>s = 0<br>if n == 0:<br>return 1 # 0! = 1<br>while n &gt; 0:<br>s += silnie[n % 10]<br>n //= 10<br>return s</p>\n<p>wyniki = []<br>with open(&#x27;liczby.txt&#x27;, encoding=&#x27;utf-8&#x27;) as f:<br>for linia in f:<br>n = int(linia.strip())<br>if suma_silni_cyfr(n) == n:<br>wyniki.append(n)</p>\n<p>for w in wyniki:<br>print(w)</p>\n<h3>2</h3>\n<h3>145</h3>\n<h3>1</h3>\n<h3>40585</h3>\n<p><strong>Weryfikacja:</strong></p>\n<ul><li>1: 1! = 1 ✓</li><li>2: 2! = 2 ✓</li><li>145: 1! + 4! + 5! = 1 + 24 + 120 = <strong>145</strong> ✓</li><li>40585: 4! + 0! + 5! + 8! + 5! = 24 + 1 + 120 + 40320 + 120 = <strong>40585</strong> ✓</li></ul>\n<h4>Sposób 2 - implementacja Pascal</h4>\n<p>```pascal<br>program SumaSilniCyfr;<br>var<br>f: TextFile;<br>n, m, suma, cyfra, i: LongInt;<br>silnie: array[0 9] of LongInt;<br>begin<br>silnie[0] := 1;<br>for i := 1 to 9 do silnie[i] := silnie[i-1] * i;<br>AssignFile(f, &#x27;liczby.txt&#x27;);<br>Reset(f);<br>while not Eof(f) do<br>begin<br>ReadLn(f, n);<br>m := n; suma := 0;<br>if m = 0 then suma := 1<br>else while m &gt; 0 do<br>begin<br>cyfra := m mod 10;<br>suma := suma + silnie[cyfra];<br>m := m div 10;<br>end;<br>if suma = n then WriteLn(n);<br>end;<br>CloseFile(f);<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>using namespace std;</p>\n<p>int silnie[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880};</p>\n<p>long long sumaSilniCyfr(long long n) {<br>if (n == 0) return 1;<br>long long s = 0;<br>while (n &gt; 0) {<br>s += silnie[n % 10];<br>n /= 10;<br>}<br>return s;<br>}</p>\n<p>int main() {<br>ifstream plik(&quot;liczby.txt&quot;);<br>long long n;<br>while (plik &gt;&gt; n) {<br>if (sumaSilniCyfr(n) == n) cout &lt;&lt; n &lt;&lt; endl;<br>}<br>return 0;<br>}</p>\n<h4>Reference informatyczny - wydobywanie cyfr liczby</h4>\n<blockquote>Reference - Algorytm na rozkład liczby na cyfry:<br>```<br>dopóki n &gt; 0<br>cyfra ← n mod 10<br>n ← n div 10<br>```<br>Złożoność: O(log₁₀(n)) - liczba cyfr.<br><br>Reference - Silnia:<br>- 0! = 1, n! = n · (n-1)! dla n &gt; 0.<br>- Rosnie szybko: 10! = 3 628 800, 12! przekracza 32-bit int.<br>- Pre-kompute: tablica silni[0 9] = [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880].<br><br>Reference - Factoriony:<br>- W dziesiętnym SĄ TYLKO 4 factoriony: 1, 2, 145, 40585. Udowodniono, że więcej nie istnieje.</blockquote>\n<h4>Schemat oceniania CKE</h4>\n<blockquote>Klucz CKE (zadanie 4.2, max 4 pkt):<br>- <strong>4 pkt</strong> - wszystkie 4 liczby (2, 145, 1, 40585) w prawidłowej kolejności<br>- <strong>1 pkt</strong> za każdą poprawną liczbę w wyniku<br>- <strong>0 pkt</strong> - błędna albo brak</blockquote>\n<h4>Typowe pułapki</h4>\n<ul><li><strong>Pominięcie 0! = 1</strong> - bez tego dla liczby 40585 wynik byłby 23+1+120+40320+120 = 40584 (lub mocno błędny).</li><li><strong>Kolejność w wyniku</strong> - musi być w kolejności pojawiania się w pliku liczby.txt (nie alfabetycznie/numerycznie).</li><li><strong>Złe wpisanie tablicy silni</strong> - najczęstszy błąd: pomylenie 5! = 120 z 6! = 720.</li><li><strong>Overflow w Pascal/C++</strong> - 9! = 362880 mieści się w 32-bit int, ale uważać dla wielocyfrowych liczb.</li><li><strong>Brak warunku zatrzymania pętli</strong> - gdy n=0 (liczba 0 nie pojawi się w danych, bo zakres 1-100000).</li></ul>\n<h4>Złożoność obliczeniowa</h4>\n<ul><li>Wczytanie pliku: O(n) - 500 wierszy.</li><li>Obliczenie sumy silni cyfr: O(log n) ≈ 6 operacji (max 6 cyfr).</li><li>Łącznie: <strong>O(n · log(max))</strong> ≈ 3000 operacji - błyskawicznie.</li><li>Pamięć: O(1) (tablica silni stała).</li></ul>"}]}