Szybkie potegowanie modulo

Szybkie potegowanie modulo
jedrzejd
  • Rejestracja:około 8 lat
  • Ostatnio:ponad 5 lat
  • Postów:25
0

Witam czy może znacie rozwiazanie problemu :
Czemu szybkie potegowanie modulo daje złą odpowiedz na 16^16 mod 10^18
o to kod

Kopiuj
unsigned long long pot_szybkie(unsigned long long a,unsigned long long n,unsigned long long q){
    unsigned long long w=1;
    while(n>0){
        if (n%2==1)w=(w*a)%q;
        a=(a*a)%q;
        n/=2;
    }
    return w%q;
}
edytowany 1x, ostatnio: jedrzejd
kq
Moderator C/C++
  • Rejestracja:prawie 12 lat
  • Ostatnio:2 dni
  • Lokalizacja:Szczecin
0

Jaką daje? Jakiej się spodziewasz? Polecam lekturę: https://dsp.krzaq.cc/post/445/jak-zadawac-pytania-na-forum/

Tutaj zapewne problemem jest to, że mnożąc 168 przez 168 wychodzi ci 1616, czyli 264, czyli liczba niemieszcząca się w zakresie twojego unsigned long long, wrapująca się do zera.


edytowany 3x, ostatnio: kq
jedrzejd
  • Rejestracja:około 8 lat
  • Ostatnio:ponad 5 lat
  • Postów:25
0

niestety trzeba bedzie wlasną artmetyke zaimplementowac :(

kq
Moderator C/C++
  • Rejestracja:prawie 12 lat
  • Ostatnio:2 dni
  • Lokalizacja:Szczecin
0

To jakieś zadanie, że będziesz musiał? Na szybko możesz Boost.Multiprecision użyć:

Kopiuj
using bigint_t = boost::multiprecision::uint1024_t;

bigint_t pot_szybkie(bigint_t a,bigint_t n,bigint_t q){
    bigint_t w=1;
    while(n>0){
        if (n%2==1)w=(w*a)%q;
        a=(a*a)%q;
        n/=2;
    }
    return w%q;
}

https://wandbox.org/permlink/g9zsJMEXNhci3HpT

Na mniej szybko i poprawniej, patrz na odpowiedź @lion137 niżej.


edytowany 1x, ostatnio: kq
lion137
  • Rejestracja:ponad 8 lat
  • Ostatnio:10 minut
  • Postów:4943
0
jedrzejd napisał(a):

niestety trzeba bedzie wlasną artmetyke zaimplementowac :(

Moze niekoniecznie: www.gmplib.org


jedrzejd
  • Rejestracja:około 8 lat
  • Ostatnio:ponad 5 lat
  • Postów:25
0

tylko ze to zadanko z algo i niewiem czy to tak mozna

lion137
  • Rejestracja:ponad 8 lat
  • Ostatnio:10 minut
  • Postów:4943
2

To Moze Zajrzyj tutaj:https://en.m.wikipedia.org/wiki/Modular_exponentiation


kq
Ale wtopa, nie znałem tego. Dzięki za link!
Shalom
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
0

Użyj square and multiply po prostu.

Kopiuj
    def square_and_multiply(base, exponent, modulus):
        binary_exponent = to_binary(exponent)
        result = 1
        for di in binary_exponent:
            square = result * result
            if di == 0:
                result = square % modulus
            else:
                result = (square * base) % modulus
        return result

"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
edytowany 1x, ostatnio: Shalom
kq
A to nie będzie miało tego samego problemu z wynikiem poza zakresem zmiennej?
Shalom
No tak, w zasadzie w tym zadaniu już z definicji trzeba własna arytmetykę bo jest mod 10^18czyli ~mod 2^57, a tym samym nie da rady czynników potęgować (bo byłyby rzędu 2^114) ani nawet mnożyć przez podstawę bo już dla podstawy 2^8 wyjdziemy poza zakres int64. Ale jeśli mamy dostępny int128 to powinno wszystko działać ;]
jedrzejd
no mamy tylko 64 bitowe zmienne
MarekR22
Moderator C/C++
  • Rejestracja:ponad 17 lat
  • Ostatnio:około 2 godziny
1

problemem jest a=(a*a)%q; a konkretniej a*a już ci wykroczy poza zakres i dzielenie mordulo już jest wykonywane na złej wartości.
Dowód:https://wandbox.org/permlink/Qpo1ZKCk9u5zi106
Trzeba zaimplementować potęgowanie modulo tu masz opis: http://eduinf.waw.pl/inf/alg/001_search/0017.php#A1


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
enedil
  • Rejestracja:prawie 12 lat
  • Ostatnio:4 dni
  • Postów:1027
0

Jeśli wiesz, że modulus jest liczbą złożoną, to możesz skorzystać z Chińskiego Twierdzenia o Resztach. Załóżmy, że n = a*b, gdzie a, b są względnie pierwsze. Wówczas wartość (x^y)%n możesz otrzymać z (x^y)%a oraz (x^y)%b za pomocją rozszerzonego algorytmu Euklidesa.

Edycja: hmm, skoro to contest algorytmiczny, to zapewne modulus będzie liczbą pierwszą :c

edytowany 1x, ostatnio: enedil
jedrzejd
możliwe ale te zadanko nie jest o potegowaniu to jest tylko pojedynczy problem w nim ;(

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.