2013-09-10 1 views
0

Нам даны 3 числа: a, s и b, каждый из которых варьируется в диапазоне от 1 до 1000000. Нам нужно найти pow (a, s)% b. Очевидно, мы не можем использовать простую функцию pow, потому что мы не смогли создать большое число, такое как 1000000 . Это решение проблемы:Нахождение найти a^s mod b

sol=1 
for(int i=0;i<s;i++) 
{ 
      sol = sol * a; 
      sol = sol % b; 
} 

print sol 

Я не понимаю этот алгоритм. Может кто-нибудь объяснить это мне?

P.S. Где можно найти больше алгоритмов для решения нетривиальных математических задач, таких как этот? Приветствия!

+1

Для записи это очень медленный алгоритм: он работает в O (s) времени. Не сложнее написать алгоритм, который работает в O (log s), что делает его пригодным для гораздо больших значений s (например, для использования в реальном RSA-шифровании). – ruakh

+2

Хмм. Да, это довольно субоптимально. Вместо повторного размножения нужно действительно попробовать повторное возведение в квадрат. –

ответ

7

Прежде всего, алгоритм, который вы написали, совсем не оптимизирован, поскольку он линейный по s, в то время как вы можете легко написать журнал (ы) один, как вы можете прочитать here.

Тем не менее, существует не так много, чтобы объяснить: вы просто должны знать, что

a*b mod N = ((a mod N) * (b mod N)) mod N 

и

a^s = a*a*...*a s times 

и сразу следует, что ваш алгоритм вычисляет результат в наивных путь.

+1

Поскольку s - 1000000, O (s) - это хорошо. Но я все еще не понимаю, что вы написали. b mod b? – Want

+0

@Want Это опечатка, извините – Save

4

сек мод Ь = (а; • с-1) мод б = (мод) • б (а с-1 мод б) по модулю Ь = ...

Как вы можете видеть, первый шаг тривиален, а второй шаг - известное свойство по модулю. Таким образом, вы можете повторить и найти s mod b.

Как вы упомянули, вы можете сделать лучше. Для другого метода вы можете перейти на Wikipedia. Но я объясню идею этого алгоритма: Представляют число s в двоичной системе, так что вы можете написать s следующим образом:

s = ∑ (2 я • б я), где каждый б я является 0 или 1.

Итак: а сек мод б = а ∑ (2 я • б я) мод б, так что вы можете просто сделать КН умножения en LSB = 1, затем сдвиг вправо экспонента ...