Существует ли алгоритм для вычисления мультипликативного порядка x по модулю y (для y <1000), который не требует типа BigInteger? - PullRequest
4 голосов
/ 13 марта 2009

Алгоритм, который я сейчас использую, очень быстро набирает очень большие числа. Шаг в алгоритме, который мне нужен, поднимает x к результату функции totient, примененной к y . В результате вы можете столкнуться с очень большими числами.

Например. При расчете мультипликативного порядка из 10 по модулю 53:

10^totient(53) == 10^52 == 1 * 10^52

Следующий алгоритм работает немного лучше с точки зрения избежания больших чисел, но все равно не работает, когда 10 ^ mOrder больше емкости типа данных:

  mOrder = 1
  while 10^mOrder % 53 != 1
      if mOrder >= i
          mOrder = 0;
          break
      else
          mOrder = mOrder + 1

Ответы [ 2 ]

7 голосов
/ 13 марта 2009

Используя модульное возведение в степень, можно вычислить (10 ^ mOrder% 53) или вообще любое (a ^ b mod c) без получения значений, намного превышающих c. См. Википедия для получения подробной информации, также есть этот пример кода:

Bignum modpow(Bignum base, Bignum exponent, Bignum modulus) {

    Bignum result = 1;

    while (exponent > 0) {
        if ((exponent & 1) == 1) {
            // multiply in this bit's contribution while using modulus to keep result small
            result = (result * base) % modulus;
        }
        // move to the next bit of the exponent, square (and mod) the base accordingly
        exponent >>= 1;
        base = (base * base) % modulus;
    }

    return result;
}
6 голосов
/ 13 марта 2009

Зачем возводить в степень? Разве вы не можете просто умножить по модулю n в цикле?

(defun multiplicative-order (a n)
  (if (> (gcd a n) 1)
      0
      (do ((order 1 (+ order 1))
           (mod-exp (mod a n) (mod (* mod-exp a) n)))
          ((= mod-exp 1) order))))

Или, в ptheudo (sic) коде:

def multiplicative_order (a, n) :
    if gcd (a, n) > 1 :
        return 0
      else:
        order = 1
        mod_exp = a mod n
        while mod_exp != 1 :
            order += 1
            mod_exp = (mod_exp * a) mod n
        return order
...