# Przydatne informacje z OBOZU C++ Największy Wspólny Dzielnik (NWD) Dla zadanych liczb a,b chcemy znaleźć najwiekszą liczbę c taką, że dzieli ona zarówno a jak i b . Na przykład NWD(18, 24) = 6 oraz NWD(6, 8) = 2. ## Obserwacja 1 Łatwo zauważyć, że każda liczba dzieli 0 , więc dla każdego a zachodzi **NWD(a,0)=a**   ## Twierdzenie 1 Jeśli c jest największym wspólnym dzielnikiem a,b oraz a≤b, to c jest też największym wspólnym dzielnikiem a−b,b. Zapisane inaczej: **NWD(a,b)=NWD(a−b,b)**   ## Obserwacja 2 Weźmy a=23 oraz b=4. Wtedy z poprzedniego twierdzenia: NWD(23,4)=NWD(19,4)=NWD(15,4)=NWD(11,4)=NWD(7,4)=NWD(3,4) Zauważmy, że to samo możemy osiągnąć w jednej operacji zamiast odejmowania robiąc modulo, bo 23%4=3   ## Twierdzenie 2 **NWD(a,b)=NWD(a%b,b)** Algorytm (Euklidesa) Mamy dwie zmienne a,b . Zamieniamy je miejscami tak, aby w a była większa liczba, a w b mniejsza. Potem w pętli dopóki obie są różne od 0 robimy a=a%b, a następnie (skoro nasze nowe a jest mniejsze od b) zamieniami te zmienne miejscami. Kiedy jedna z tych zmiennych jest równa 0 , przerywamy pętlę i wypisujemy drugą liczbę jako NWD.   ## NWW Mając NWD umiemy obliczyć Najwiekszą Wspólną Wielokrotność (NWW) dwóch liczb ze wzoru: **NWW(a,b)=(a⋅b)/NWD(a,b)** # Zmienne znakowe i napisy ## Zmienne typu char(acter) W C++ mamy do dyspozycji typ dla zmiennych znakowych. W zmiennych tych mogą być trzymane wartości z zakresu [−128,127] . Funkcje wyjścia/wejścia interpretują odpowiednio typ znakowy, wypisując zamiast znajdującej się w zmiennej liczbę, odpowiadający tej liczbie znak z tabeli ASCII. ## Znak a liczba Skoro wiemy, że znaki to tak naprawdę liczby, nie musimy pamiętać wartości tablicy ASCII. W kodzie znak traktowany jest po prostu jak liczba typu char. Przykład: '!' + '$' == 33 + 36 == 69 == 'E' Sprawdzanie wielkości litery ```cpp= char c; cin>>c; if(c >= 'a' && c <= 'z') cout<<"mala litera\n"; else if (c >= 'A' && c <= 'Z') cout<<"wielka litera\n"; else cout<<"nie litera\n"; ``` Zamiana wielkiej litery na małą ```cpp=char c; cin>>c; //zakładamy tu, że c to znak o wartości pomiędzy [65, 90] c = c + 32; cout<<c<<'\n'; ``` Zamiana cyfry na liczbę ```cpp= char c; cin>>c; //zakładamy tu, że c to znak o wartości pomiędzy [48, 57] int a = c - '0'; ``` # Tablice dwuwymiarowe int tab[n][m] oznacza, że deklarujemy tablicę wielkości nxm, gdzie n interpretujemy jako liczba wierszy, a m jako liczba kolumn. Poniżej znajduje się przykładowy kod do tablic dwuwymiarowych: ```cpp= #include <iostream> using namespace std; int tab[100][100]; int wie = 100, kol=100; int main(){ int licznik=0; for(int w=0; w<wie; w++){ for(int k=0; k<kol; k++){ tab[w][k]=licznik; licznik++; } } for(int w=0; w<wie; w++){ for(int k=0; k<kol; k++){ cout<<tab[w][k]<<" "; } cout<<"\n"; } } ``` ## O macierzach: Macierz to tablica dwuwymiarowa. Macierze można dodawać, odejmować i mnożyć przez liczbę. ## Wskazówki do kodu: Lepiej pisać zmienne w taki sposób, żeby od razu było wiadomo, co oznaczają: ```cpp= int wiersze;// liczba wierszy int kolumny; // liczba kolumn ``` albo ```cpp= int wie; //liczba wierszy int kol; //liczba kolumn ``` Jeśli zadanie nie wymaga innego sposobu - najlepiej jest iterować się najpierw po wierszach a potem po kolumnach: ```cpp= for(int w=0; w<wie; w++){ for(int k=0; k<kol; k++){ //wasz kod } } ``` # Tablice jednowymiarowe ## Tablice domyślnie deklarujemy w przestrzeni globalnej. Przykłady: ```cpp= #include <iostream> using namespace std; // (przestrzeń globalna) // np. dla n <= 10^6 int tab[1000006]; // <- zawsze deklarujemy trochę więcej niż potrzebujemy // ↑ tablice tworzone w przestrzeni globalnej są wyzerowane. // ciekawostka, że tak można const int P = 1e6+6; int tab2[P]; // za pomocą nawiasów klamrowych, // można przypisywać wartości do tablicy przy jej tworzeniu. int test[3]={1,2,3}; int main(){ int c; // <- UWAGA! Zmienna bez zainicjalizowanej wartości int tab3[100]={}; // <- tak też stworzymy wyzerowaną tablicę // jednkaże zwykle nie deklarujemy dużych tablic w funkcjach, // a w przestrzeni globalnej // ❌ TAK NIE ROBIMY: tab3[100] = 3; // <- tab3 ma zakres od 0 do 99 cout<<tab3[105]; // <---------------------------- tab = 7; // tab to wskaźnik na tablicę, a nie zmienna! cout<<tab; //<- to nie wypisze nam całej tablicy :( int n; cin>>n; int tab4[n]; // NIE WOLNO TAK ROBIĆ! W języku C jest to nielegalne. ... ``` # Warto wiedzieć! Typ int ma 4 bajty = 32 bity. W zmiennej typu int możemy trzymać liczby od −231 (~ -2mld.) do 231−1 (~ 2 mld.) Trzeba pamiętać, że gdy nie przypisujemy wartości danej komórce pamięci, to znajduje się tam losowa wartość (tak jak znak zapytania w maszynie RAM). Zadania na Themisie i na konkursach często mają limit pamięci. Jednym z przeliczników, które warto znać jest ten, że tablica miliona intów ma rozmiar 4MB. Deklarując tablicę musimy pamiętać o jej odpowiedniej wielkości. Nie możemy jako programiści dopuścić do zaglądania w “nie naszą pamięć”. Np. próba odczytu lub zapisu do komórki spoza tablicy, w zadaniu na Themisie, np. tab[-1], lub tab[10] (dla tablicy 10 elementowej), zakończy się odpowiednim błędem. Próba zapisu liczby o typie innym niż zmienna do której zapisujemy, nie zakończy się błędem. Program wykona swoje zadanie, odpowiednio ucinając liczbę, lub modyfikując ją w inny sposób. Np. cout<<(int)(3.5); wypisze liczbę 3. By przyspieszyć działanie programu poprzez wyłączenie synchronizacji strumieni (i innych niepotrzebnych nam elementów) dodajemy na początku funkcji main linijki: ```cpp= ios_base::sync_with_stdio(false); cin.tie(0); ```