2009-03-13 1 views
4

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

Например. При расчете multiplicative order из 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 
+0

Не часть первоначального вопроса, но аккуратный способ совместить ответы от @schnaader и @Svante. Требуемый мультипликативный порядок должен делить тотал (с), поэтому вам не нужно проверять каждый a^b. Если вы перечислите делители totient (c), вы можете использовать метод @ schnaader для выполнения возведения в степень, а метод @ Svante использовать уже рассчитанные результаты для вычисления других - т. Е. 10^1, 10^2 (путем возведения в квадрат), 10^4 (путем возведения в квадрат), 10^13 = (10^4)^3 * (10^1), 10^26 (путем возведения в квадрат). (Если это ни один из них, это должно быть 52). –

ответ

7

Использование модульного возведения в степень, можно вычислить (10^Morder% 53) или в общем, любой (а^Ь мод с) без получения значения намного больше, чем с. См Wikipedia подробности, есть этот пример кода, тоже:

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; 
} 
+1

+1 - мой ответ точно, всего на 1 минуту раньше :) –

+1

Не могу поверить, что я забыл об этом, особенно учитывая, что использовал его два дня назад. Я полагаю, мне нужен кофе. – ilitirit

+1

Или, возможно, после сна и кофе;) – schnaader

6

Почему экспоненциируются? Не можете ли вы просто умножить по модулю n в цикле?

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

Или, в ptheudo (СИК) код:

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