2012-01-07 6 views
4

У меня есть 50 000 номеров (может варьироваться от 0 до 50 000). И мне нужно (произведение этих чисел) MOD 1000000007. Следующий код настолько тривиален, должны быть другие способы. Слышал о методах «Разделить и побеждать», но понятия не имею, как их реализовать.Быстрое умножение очень больших чисел в perl

$ans *= ($_ % 1000000007) foreach @array; 
$ans %= 1000000007; 

Просьба предложить.

+3

Если каждое число в '@ array' является <50000, то' $ _% 1000000007' ничего не изменит, так как рассчитывается до умножения. – TLP

ответ

1

Хотя вы делаете $_ % 1000000007 на каждом номере вашего массива, ваш $ans может стать очень большим, пока вы, наконец, не сделаете $ans %= 1000000007 после просмотра.

Чтобы исправить это я предлагаю следующее:

foreach my $number (@array) 
{ 
    $ans *= ($number % 1000000007); 
    $ans %= 1000000007; 
} 
+3

Вы можете опустить '($ number% 1000000007)' и сделать просто '$ ans * = $ number'. Числа составляют до 50 000 (и даже для больших чисел нет причин делать% дважды). – ugoren

7

Результат $num % 1000000007 всегда будет $num для всех значений меньше, чем 1000000007. Так что, если все значения в @array находятся в диапазоне 0 .. 50000, такой расчет является избыточным. Вы должны сделать два шага, а не использовать *= оператора:

$ans = ($ans % 1000000007) * $_ for @array; 

Слово предостережения, хотя. Для любого несвязанного modulo всегда существует риск того, что ваша операция по модулю приведет к нулю, что, конечно же, вызовет полное умножение на нуль. Думаю, вы уже об этом подумали, так как 1000000007, кажется, простое число, но я все равно упомянул об этом.

ETA: Повторное использование промежуточных продуктов:

for (@array) { 
    $ans *= $_; 
    print "Before mod: $ans\n"; 
    $ans %= 1000000007; 
    print "After mod : $ans\n"; 
} 

Обратите внимание, что вам не нужно усугублять операторов здесь.

+0

Спасибо, что указали на избыточность, есть ли способ, который мы можем повторно использовать для промежуточных результатов умножения? .. – trinity

+0

@trinity Reuse? Ну, с постфиксным циклом, это будет сложно, и, честно говоря, этого не стоит. Я добавлю пример. – TLP

1

Если вычислительное повторное использование является важным/ожидаемым (как указано в комментарии к ответу TLP), то memoizing функция поможет ускорить, эффективно запоминая ранее рассчитанные результаты.

См Chapter 3: Caching and Memoization in Higher-Order Perl

 Смежные вопросы

  • Нет связанных вопросов^_^