Zadanie trzeba było rozwiązać zauważając powtarzalność ostatniej cyfry potęgowanej liczby, zwykłe potęgowanie byłoby zbyt złożone obliczeniowo dla podanego zestawu.
Jak zauważyć powtarzalność? Kartka papieru, rozpisać ostatnie cyfry dla 0^1, 0^2, …., 1^1, 1^2, 1^3, …, 9^5 itd.
Potem zapisać odpowiednią tabelę w kodzie, tak aby program sięgał jedynie po odpowiednią wartość z tabeli, zamiast obliczać.
To jak długo wykonuje się progam można sprawdzić pod linuxem za pomocą polecenia ‘time’, np. ‘time wget google.com’, jeśli ktoś chce porównać zwykłą implementację z tą z opisanym chwytem.
Można tu jeszcze użyć stdlib lub wyłączyć synchronizację io w iostream, ale to drobiazgi.
Kod:
#include <iostream>
using namespace std;
int main() {
unsigned short results[10][1][4] = {{{0}},{{1}},{{6,2,4,8}},
{{1,3,9,7}},{{6,4}},{{5}},{{6}},{{1,7,9,3}},{{6,8,4,2}},{{1,9}},};
unsigned short modulo[] = {1, 1, 4, 4, 2};
long n;
cin >> n;
long cases[n][2];
for (long a = 0; a < n; a++)
cin >> cases[a][0] >> cases[a][1];
for (long a = 0; a < n; a++) {
unsigned short moduloDivisorIndex = (cases[a][0] % 5);
unsigned short moduloDivisor = modulo[moduloDivisorIndex];
unsigned short lastDigit = cases[a][0] % 10;
long moduloIndex = cases[a][1] % moduloDivisor;
cout << results[lastDigit][0][moduloIndex] << '\n';
}
cout << endl;
return 0;
}
Wersja z komentarzem:
#include <iostream>
using namespace std;
int main() {
//1 indeks jaka jest ostatnia cyfra podstawy
//3 jaki jest wynik modulo przez komórkę z modulo[]
unsigned short results[10][1][4] = {
{ //0
{0}
},{
//1
{1}
},{
//2
{6, 2, 4, 8}
},{
//3
{1, 3, 9, 7}
},{
//4
{6, 4}
},{
//5
{5}
},{
//6
{6}
},{
//7
{1, 7, 9 ,3}
},{
//8
{6, 8, 4, 2}
},{
//9
{1, 9}
},
};
unsigned short modulo[] = {1, 1, 4, 4, 2};
//Pattern na modulo: 1 4 4 2 1
//Modulo przez 5
//Dla 1 - 1
//Dla 2 - 4
//Dla 3 - 4
//Dla 4 - 2
//Dla 0 - 1
//Liczba: 1
//Potęgi 1 2 3 4 5 6 7 8 9
//Wyniki:1 1 1 1 1 1 1 1 1
//Powtarzanie: [1]
//Liczba: 2
//Potęgi 1 2 3 4 5 6 7 8 9
//Wyniki:2 4 8 16 32 64 128 256 512
//Powtarzanie: [2 4 8 6]
//Modulo przez 4:
//1 - 2
//2 - 4
//3 - 8
//0 - 6
//Liczba: 3
//Potęgi 1 2 3 4 5
//Wyniki:3 9 27 81 243
//Powtarzanie: [3 9 7 1]
//Modulo przez 4:
//1 - 3
//2 - 9
//3 - 7
//0 - 1
//Liczba: 4
//Potęgi 1 2 3 4 5
//Wyniki:4 16 64 256 1024
//Powtarzanie: [4 6]
//Modulo przez 2:
//1 - 4
//0 - 6
//Liczba: 5
//Potęgi 1 2 3 4
//Wyniki:5 25 125 625
//Powtarzanie: [5]
//Modulo przez 1:
//0 - 5
//Liczba: 6
//Potęgi 1 2 3 4
//Wyniki:6 36 216 1296
//Powtarzanie: [6]
//Modulo przez 1:
//0 - 6
//Liczba: 7
//Potęgi 1 2 3 4 5
//Wyniki:7 49 343 2401 16807
//Powtarzanie: [7 9 3 1]
//Modulo przez 4:
//1 - 7
//2 - 9
//3 - 3
//0 - 1
//Liczba: 8
//Potęgi 1 2 3 4 5
//Wyniki:8 64 512 4096 32768
//Powtarzanie: [8 4 2 6]
//Modulo przez 4:
//1 - 8
//2 - 4
//3 - 2
//0 - 6
//Liczba: 9
//Potęgi 1 2 3 4 5
//Wyniki:9 81 729 6561 59049
//Powtarzanie: [9 1]
//Modulo przez 2:
//1 - 9
//0 - 1
//Liczba: 10
//Potęgi 1
//Wyniki:10
//Powtarzanie: [0]
//Modulo przez 1:
//0 - 0
long n;
cin >> n;
long cases[n][2];
for(long a =0;a<n;a++)
cin >> cases[a][0] >> cases[a][1];
for(long a =0;a<n;a++){
unsigned short moduloDivisorIndex = (cases[a][0] % 5);
// cout << "Modulo divisor index: " << moduloDivisorIndex << endl;
unsigned short moduloDivisor = modulo[moduloDivisorIndex];
// cout << "Modulo divisor: " << moduloDivisor << endl;
unsigned short lastDigit = cases[a][0] % 10;
// cout << "Last digit: " << lastDigit << endl;
long moduloIndex = cases[a][1] % moduloDivisor;
// cout << "Modulo index: " << moduloIndex << endl;
cout << results[lastDigit][0][moduloIndex] << '\n';
}
cout << endl;
return 0;
}