Potęgowanie C++

Potęgowanie C++
CR
  • Rejestracja:ponad 4 lata
  • Ostatnio:ponad 4 lata
  • Postów:64
0
Kopiuj
#include <iostream>
    #include<math.h>

    using namespace std;


    int main()
    {

    	int ilosc, a, b, c;

    	cout << "Ile liczb chcesz wpisac?: ";
    	cin >> ilosc;

    	for (int i = 0; i < ilosc; i++)
    	{
    		cout << "wpisz podstawe a i b " << endl;
    		cin >> a >> b;
    		c = pow(a, b);
    		if (c < 10)
    			cout << c << endl;
    		else {
    			c = c % 10;
    			cout << c << endl;
    		}
    	}

    	
    }

Dla danych dwóch liczb naturalnych a i b, wyznaczyć ostatnią cyfrę liczby ab.

Zadanie
Napisz program, który:
wczyta ze standardowego wejścia: podstawę a oraz wykładnik b,
wyznaczy ostatnią cyfrę liczby ab,
wypisze wynik na standardowe wyjście.
Wejście
W pierwszej linii wejścia znajduje się jedna liczba całkowia D (1≤D≤10), oznaczjąca liczbę przypadków do rozważenia. Opis każdego przypadku podany jest w jednym wierszu, zawierającym dwie liczby naturalne a i b oddzielone pojedynczym odstępem (spacją), takie, że (1 ≤ a,b ≤ 1 000 000 000).

Wyjście
Dla każdego przypadku z wejścia Twój program powinien wypisać (w osobnej linii dla każdego przypadku z wejścia) cyfrę jedności liczby ab zapisanej dziesiętnie.

Przykład
Dla danych wejściowych:
2
2 3
3 3
poprawną odpowiedzią jest:
8
7

to mój kod, wedle podanego zadania i przykładu działa, ale sędzia nie uznaje, ktoś podpowie?

edytowany 3x, ostatnio: crypton
AK
dokłądnie taki sam wątek był 3 dni temu.
kq
Imo lepiej żeby każdy miał swój niż się dokładał do czyjegoś. Szczególnie jeśli ułatwi to zrozumienie problemu.
AK
kq
Moderator C/C++
  • Rejestracja:prawie 12 lat
  • Ostatnio:3 minuty
  • Lokalizacja:Szczecin
1

Przede wszystkim, nie działa poprawnie dla przykładu

Kopiuj
2
2 3
3 3

Poprawną odpowiedzią jest:

Kopiuj
8
7

Twój skrypt odpowiada:

Kopiuj
Ile liczb chcesz wpisac?: 

wpisz podstawe a i b 
8
wpisz podstawe a i b 
7

Ale podstawowym problemem tutaj jest to, że odpowiedzi bardzo szybko wyjdą poza zakres dowolnego typu liczbowego (w tym double zwracanego przez pow()), i trzeba zauważyć pewne zależności charakteryzujące wyniki. Np. to, że są okresowe.


CR
  • Rejestracja:ponad 4 lata
  • Ostatnio:ponad 4 lata
  • Postów:64
0

jak zauwazylem, moj kod bedzie tylko dla liczb 2 cyfrowych poprawny, bo jesli bedzie 3 cyfrowa to zwroci druga liczbe, ale jak temu zaradzic?

kq
Moderator C/C++
  • Rejestracja:prawie 12 lat
  • Ostatnio:3 minuty
  • Lokalizacja:Szczecin
1

Nie bardzo wiem jak doszedłeś do takiego wniosku. Ale mam taką sugestię: policz sobie kolejne potęgi np. liczby 4. Albo 14. Najlepiej pisemnie, żebyś zauważył które cyfry wpływają na wartość ostatniej cyfry wyniku. Może zauważysz pewną zależność.


CR
  • Rejestracja:ponad 4 lata
  • Ostatnio:ponad 4 lata
  • Postów:64
1

ostatnie cyfry potęgi liczby: (>10)
2 to 2,4,6,8
3 to 1,3,7,9
4 to 6,4
5 to 5
6 to 6
7 to 1,3,7,9
8 to 2,4,6,8
9 to 9,1

o to chodzi?

kq
Moderator C/C++
  • Rejestracja:prawie 12 lat
  • Ostatnio:3 minuty
  • Lokalizacja:Szczecin
0

Dokładnie tak. Teraz wystarczy to ubrać w kod i masz zadanie rozwiązane (+ wziąć pod uwagę moją uwagę z pierwszego posta)


CR
  • Rejestracja:ponad 4 lata
  • Ostatnio:ponad 4 lata
  • Postów:64
0

czyli jeszcze zamiast int, dac long double tak?

AK
czyli nie zrozumiałeś ...
kq
Moderator C/C++
  • Rejestracja:prawie 12 lat
  • Ostatnio:3 minuty
  • Lokalizacja:Szczecin
1

Nie, int jest tutaj poprawnym typem danych. double jest typem zmiennoprzecinkowym, a Ty ułamków nigdzie jego właściwości tu nie potrzebujesz. Wręcz przeciwnie.

Chodziło mi o to, że wypisujesz znacznie więcej tekstu niż wymaga tego zadanie. To jest błąd.


edytowany 1x, ostatnio: kq
CR
  • Rejestracja:ponad 4 lata
  • Ostatnio:ponad 4 lata
  • Postów:64
0

czyli pętlę zostawić, a potem ify dla kazdej podstawy od 2 do 9?

kq
Moderator C/C++
  • Rejestracja:prawie 12 lat
  • Ostatnio:3 minuty
  • Lokalizacja:Szczecin
0

A co z 0 i 1?


CR
  • Rejestracja:ponad 4 lata
  • Ostatnio:ponad 4 lata
  • Postów:64
0

0 do jakiejkolwiek potęgi da 0, zaś 1 da zawsze 1

kq
Moderator C/C++
  • Rejestracja:prawie 12 lat
  • Ostatnio:3 minuty
  • Lokalizacja:Szczecin
0

No tak. Ale nie możesz zapomnieć ich wziąć pod uwagę. Najlepiej by było gdybyś zrobił sobie osobną funkcję do liczenia ostatniej cyfry n-tej potęgi danej liczby i po prostu w pętli ją odpalał. Ale jeśli tego nie chcesz robić to spróbuj po swojemu i pokaż efekt.


CR
  • Rejestracja:ponad 4 lata
  • Ostatnio:ponad 4 lata
  • Postów:64
0

teraz tylko jak sprawdzić, który przypadek jest prawidlowy dla danej liczby, przykładowo a=2, b=5, zadziała if (a==2), ale z dwójką przypadków jest cztery (2,4,6,8)

kq
Moderator C/C++
  • Rejestracja:prawie 12 lat
  • Ostatnio:3 minuty
  • Lokalizacja:Szczecin
0

Przypadki są zawsze w tej samej kolejności, użyj modulo.


CR
  • Rejestracja:ponad 4 lata
  • Ostatnio:ponad 4 lata
  • Postów:64
0
Kopiuj
#include <iostream>
#include<cmath>

using namespace std;


int liczeniepotegi(int a, int b)
{
    int wynik;
    if (a == 0)
        return 0;
    else if (a == 1)
        return 1;
    else if (a == 2)
    {
        wynik = pow(a, b);
        wynik = wynik % 10;
        return wynik;
    }
    else if (a == 3)
    {
        wynik = pow(a, b);
        wynik = wynik % 10;
        return wynik;
    }
    else if (a == 4)
    {
        wynik = pow(a, b);
        wynik = wynik % 10;
        return wynik;
    }
    else if (a == 5)
    {
        return 5;
    }
    else if (a == 6)
    {
        return 6;
    }
    else if (a == 7)
    {
        wynik = pow(a, b);
        wynik = wynik % 10;
        return wynik;
    }
    else if (a == 8)
    {
        wynik = pow(a, b);
        wynik = wynik % 10;
        return wynik;
    }
    else if (a == 9)
    {
        wynik = pow(a, b);
        wynik = wynik % 10;
        return wynik;
    }

}



int main()
{

    int ilosc, a, b, c;

    cout << "Ile liczb chcesz wpisac?: ";
    cin >> ilosc;

    for (int i = 0; i < ilosc; i++)
    {
        cout << "wpisz podstawe a i b " << endl;
        cin >> a >> b;
        cout << liczeniepotegi(a, b);
        
    }
    

}

coś takiego udalo mi sie napisać, niby dla przypadków dobrze, ale dla pewnosci spytam xd

edytowany 1x, ostatnio: crypton
AK
zdrowiej będzie, jak nazwa funkcji będzie prawdziwsza np LiczenieOstCyfryPotegi. Nazwy są ważne, nie tylko lepiej dokumentują, ale wpływają na myślenie "psychologicznie"
AK
oczywiście krytyka pow() od kq jest słuszna
kq
Z nazwą trafna uwaga, za bardzo skupiłem się wyłącznie na funkcjonalności.
kq
Moderator C/C++
  • Rejestracja:prawie 12 lat
  • Ostatnio:3 minuty
  • Lokalizacja:Szczecin
1

Ookej... Zależność zauważyłeś, ale zupełnie olałeś. Użycie pow() w tym zadaniu to błąd.

Może to Ci pomoże - na przykładzie liczby 2:

wykładnik ostatnia cyfra
1 2
2 4
3 8
4 6
5 2
6 4
7 8
8 6

Widzisz zależność? Użyj jej.


CR
  • Rejestracja:ponad 4 lata
  • Ostatnio:ponad 4 lata
  • Postów:64
0

tak, wcześniej już zauwazylem ale szczerze mówiąc, nie mam pojecia jak jej użyć

kq
Moderator C/C++
  • Rejestracja:prawie 12 lat
  • Ostatnio:3 minuty
  • Lokalizacja:Szczecin
1

Jak już pisałem - użyj modulo/reszty z dzielenia. Masz kolejnego hinta:

wykładnik | wykładnik modulo okres (4) | ostatnia cyfra
---------------- | -------------------
1 | 1 | 2
2 | 2 | 4
3 | 3 | 8
4 | 0 | 6
5 | 1 | 2
6 | 2 | 4
7 | 3 | 8
8 | 0 | 6
9 | 1 | 2
10 | 2 | 4


CR
  • Rejestracja:ponad 4 lata
  • Ostatnio:ponad 4 lata
  • Postów:64
0
Kopiuj
#include <iostream>
#include<cmath>

using namespace std;


int  LiczenieOstCyfryPotegi(int a, int b)
{
    int wynik;
    if (a == 0)
        return 0;
    else if (a == 1)
        return 1;
    else if (a == 2)
    {
        if (b % 2 == 0)
            return 4 albo 6;
        else return 2 albo 8;
    }
    else if (a == 3)
    {
        if (b % 2 == 0)
            return 9 albo 1;
        else return 3 albo 7;
    }
    else if (a == 4)
    {
        if (b % 2 == 0)
            return 6;
        else return 4;

    }
    else if (a == 5)
    {
        return 5;
    }
    else if (a == 6)
    {
        return 6;
    }
    else if (a == 7)
    {
        if (b % 2 == 0)
            return 4 albo 1;
        else return 7 albo 3;
    }
    else if (a == 8)
    {
        if (b % 2 == 0)
            return 4 albo 6;
        else return 8 albo 2;
    }
    else if (a == 9)
    {
        if (b % 2 == 0)
            return 1;
        else return 9;
    }

}



int main()
{

    int ilosc, a, b, c;

    cout << "Ile liczb chcesz wpisac?: ";
    cin >> ilosc;

    for (int i = 0; i < ilosc; i++)
    {
        cout << "wpisz podstawe a i b " << endl;
        cin >> a >> b;
        cout << LiczenieOstCyfryPotegi(a, b);
        
    }
    

}

chyba zczailem koncept, ale nie wiem jeszcze jak poradzic sobie z poczwórnymi warunkami, bo podwójne po prostu rozdzieliłem je na warunki parzyste i nieparzyste

i wiem ( pogladowo dalem sobie to "albo", bo nie wiem jak sobie z tym poradzić)

edytowany 1x, ostatnio: crypton
kq
Moderator C/C++
  • Rejestracja:prawie 12 lat
  • Ostatnio:3 minuty
  • Lokalizacja:Szczecin
0

No już blisko, ale nie zauważyłeś, że jak okres jest 4 (tak jak w przykładzie, który ztablicowałem wyżej) to istotna jest wartość modulo okres, a nie modulo 2.

Może kolorki pomogą.

screenshot-20201031150744.png


edytowany 1x, ostatnio: kq
CR
  • Rejestracja:ponad 4 lata
  • Ostatnio:ponad 4 lata
  • Postów:64
0
Kopiuj
#include <iostream>
#include<cmath>

using namespace std;


int  LiczenieOstCyfryPotegi(int a, int b)
{
    int wynik;
    if (a == 0)
        return 0;
    else if (a == 1)
        return 1;
    else if (a == 2)
    {
        if (b % 4 == 1)
            return 2;
        else if (b % 4 == 2)
            return 4;
        else if (b % 4 == 3)
            return 8;
        else if (b % 4 == 0)
            return 6;
    }
    else if (a == 3)
    {
        if (b % 4 == 1)
            return 3;
        else if (b % 4 == 2)
            return 9;
        else if (b % 4 == 3)
            return 7;
        else if (b % 4 == 0)
            return 1;
    }
    else if (a == 4)
    {
        if (b % 2 == 0)
            return 6;
        else return 4;

    }
    else if (a == 5)
    {
        return 5;
    }
    else if (a == 6)
    {
        return 6;
    }
    else if (a == 7)
    {
        if (b % 4 == 1)
            return 7;
        else if (b % 4 == 2)
            return 9;
        else if (b % 4 == 3)
            return 3;
        else if (b % 4 == 0)
            return 1;
    }
    else if (a == 8)
    {
        if (b % 4 == 1)
            return 2;
        else if (b % 4 == 2)
            return 4;
        else if (b % 4 == 3)
            return 8;
        else if (b % 4 == 0)
            return 6;
    }
    else if (a == 9)
    {
        if (b % 2 == 0)
            return 1;
        else return 9;
    }

}



int main()
{

    int ilosc, a, b, c;

    cout << "Ile liczb chcesz wpisac?: ";
    cin >> ilosc;

    for (int i = 0; i < ilosc; i++)
    {
        cout << "wpisz podstawe a i b " << endl;
        cin >> a >> b;
        cout << LiczenieOstCyfryPotegi(a, b);
        
    }
    

}

chyba dobrze i do tego zrozumialem skad to sie wzielo i jak to napisać

edytowany 1x, ostatnio: crypton
kq
Moderator C/C++
  • Rejestracja:prawie 12 lat
  • Ostatnio:3 minuty
  • Lokalizacja:Szczecin
1

Już całkiem nieźle. Teraz jeszcze musisz wziąć pod uwagę potęgę 0 (cokolwiek do 0 to zawsze 1) oraz to, że niepoprawnie wypisujesz - masz wypisywać tylko wyniki, a nie zapytania do użytkownika.


enedil
  • Rejestracja:prawie 12 lat
  • Ostatnio:3 dni
  • Postów:1027
0

Tak naprawdę to można przejmować się zawsze resztą z dzielenia przez 4, a nie przez 2, co może uprościć znacząco kod. Jak już napiszesz coś co działa, to mogę wrzucić zgrabne rozwiązanie.

edytowany 2x, ostatnio: enedil
CR
  • Rejestracja:ponad 4 lata
  • Ostatnio:ponad 4 lata
  • Postów:64
0
enedil napisał(a):

Tak naprawdę to można przejmować się zawsze resztą z dzielenia przez 4, a nie przez 2, co może uprościć znacząco kod. Jak już napiszesz coś co działa, to mogę wrzucić zgrabne rozwiązanie.

teraz o tym wiem, wtedy jak pisalem latwiej bylo mi zrozumieć poprzez %2

CR
  • Rejestracja:ponad 4 lata
  • Ostatnio:ponad 4 lata
  • Postów:64
0
kq napisał(a):

Już całkiem nieźle. Teraz jeszcze musisz wziąć pod uwagę potęgę 0 (cokolwiek do 0 to zawsze 1) oraz to, że niepoprawnie wypisujesz - masz wypisywać tylko wyniki, a nie zapytania do użytkownika.

no tak zgadza się, bo wcześniej chodzi o wykładnik (a do 0 = a) , a nie o podstawę (0 do a = 0)

CR
  • Rejestracja:ponad 4 lata
  • Ostatnio:ponad 4 lata
  • Postów:64
0
Kopiuj
#include <iostream>
#include<cmath>

using namespace std;


int  LiczenieOstCyfryPotegi(int a, int b)
{
    int wynik;
    if (b == 0)
        return 1;
    else if (a == 1)
        return 1;
    else if (a == 2)
    {
        if (b % 4 == 1)
            return 2;
        else if (b % 4 == 2)
            return 4;
        else if (b % 4 == 3)
            return 8;
        else if (b % 4 == 0)
            return 6;
    }
    else if (a == 3)
    {
        if (b % 4 == 1)
            return 3;
        else if (b % 4 == 2)
            return 9;
        else if (b % 4 == 3)
            return 7;
        else if (b % 4 == 0)
            return 1;
    }
    else if (a == 4)
    {
        if (b % 2 == 0)
            return 6;
        else return 4;

    }
    else if (a == 5)
    {
        return 5;
    }
    else if (a == 6)
    {
        return 6;
    }
    else if (a == 7)
    {
        if (b % 4 == 1)
            return 7;
        else if (b % 4 == 2)
            return 9;
        else if (b % 4 == 3)
            return 3;
        else if (b % 4 == 0)
            return 1;
    }
    else if (a == 8)
    {
        if (b % 4 == 1)
            return 2;
        else if (b % 4 == 2)
            return 4;
        else if (b % 4 == 3)
            return 8;
        else if (b % 4 == 0)
            return 6;
    }
    else if (a == 9)
    {
        if (b % 2 == 0)
            return 1;
        else return 9;
    }

}



int main()
{

    int ilosc, a, b;
    
    
    cin >> ilosc;
    int* tab = new int[ilosc];

    for (int i = 0; i < ilosc; i++)
    {
        
        cin >> a >> b;
        tab[i]= LiczenieOstCyfryPotegi(a, b);

    }
    for (int i = 0; i < ilosc; i++) {
        cout << tab[i] << endl;
    }

}

ostatecznie zmodyfikowany kod

edytowany 1x, ostatnio: crypton
kq
Moderator C/C++
  • Rejestracja:prawie 12 lat
  • Ostatnio:3 minuty
  • Lokalizacja:Szczecin
1

Cały czas nie obsługujesz zerowego wykładnika.

Po co dodałeś dynamiczną alokację i tablicę? Wcześniej było dobrze


enedil
I don't wanna be this guy, ale treść zadania mowi, że 1 <= a, b. Oczywiście wypadałoby się tym zająć, ale nie ma konieczności.
kq
Bądź tym guyem, nie zauważyłem tego ;​) ALE i tak bym zrobił checka, bo zadania na SPOJu często mają błędne opisy/testery ;​(
enedil
  • Rejestracja:prawie 12 lat
  • Ostatnio:3 dni
  • Postów:1027
1

Ok, to skoro padło już jakieś rozwiązanie, to prezentuję własne, całkiem chyba zwięzłe:

Kopiuj
#include <iostream>
#include <cmath>

unsigned PowMod10(unsigned a, unsigned b) {
    if (b == 0)
        return 1;
    // Nie będzie ani przepełnienia ani utraty precyzji double, gdyż wynik
    // nie przekroczy 9^(4+3) < 10^9 < 2^31 < 2^53.
    // Oczywiście, można by to zaimplementować przez zwykłą pętlę, ale w
    // tym zastosowaniu to bez różnicy z punktu widzenia poprawności/wydajności,
    // a przynajmniej jest mniej kodu.
    return ((unsigned)pow(a % 10, 4 + b%4)) % 10;
}

int main() {
    int D;
    std::cin >> D;
    while (D--) {
        unsigned a, b;
        std::cin >> a >> b;
        std::cout << PowMod10(a, b) << "\n";
    }
}
CR
  • Rejestracja:ponad 4 lata
  • Ostatnio:ponad 4 lata
  • Postów:64
0

dodalem by output jaki jest podany w zadaniu byl taki sam, inaczej zamiast:
Przykład
Dla danych wejściowych:
2
2 3
3 3
poprawną odpowiedzią jest:
8
7

miałbym

2
2 3
8
3 3
7

co do pierwszego >>> if (a == 0)
return 1;
powinno być if (b == 0)
return 1;

enedil
Nie, to serio działa poprawnie - znaki które Ty wprowadzasz są pomiędzy tymi wypisywanymi, ale testerka w inny sposób je czyta, i nie ma problemu z tym, że się przeplatają.
enedil
Też kiedyś myślałem jak Ty i to nastręczało nieco problemów. Zasada jest taka, że to co będzie na cout w dobrej kolejności będzie przeczytane przez testerkę, to co wpiszesz na cin w dobrej kolejności, będzie w dobrej kolejności przeczytane. To są zupełnie odrębne rzeczy.
CR
  • Rejestracja:ponad 4 lata
  • Ostatnio:ponad 4 lata
  • Postów:64
0

bądź co bądź wysłany kod na SPOJ, nie działa

enedil
No ale nie jest to kwestia złej kolejności wejścia/wyjścia

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.