Блог пользователя lth

Автор lth, 15 лет назад, По-русски

Всегда писал Миллера-Рабина для чисел в пределах [1, 2 ^ 31 - 1]. И вчера на одном OJ попалась задача,где нужно писать вышеупомянутый тест на простоту для чисел [1, 2 ^ 63 - 1].Все отлично, но вот возводить в степень за log(n) не получается.При возведении промежуточные результаты выходят за пределы long long.Не подскажите ли, знающие люди, как ето можно сделать ?

  • Проголосовать: нравится
  • 0
  • Проголосовать: не нравится

»
15 лет назад, скрыть # |
 
Проголосовать: нравится +1 Проголосовать: не нравится
есть алгоритм "безопасного умножения по модулю". По сути тоже что и возведение в степень по модулю модулю, но тут вместо умножения - сложение, а вместо возведения в квадрат - умножение на 2.
»
15 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится
что - то типа (u64 = unsigned long long)
u64 mulmod(u64 a, u64 b, u64 mod)
{
if(b&1)
return (mulmod(a, b-1, mod) + a)%mod;
else
return mulmod((a+a)%mod, b>>1, mod);
}
»
15 лет назад, скрыть # |
 
Проголосовать: нравится +1 Проголосовать: не нравится
Есть два трюка первый это "бинарное умножение", это так-же как возведение в степень, только все умножения заменяются на сложения.
То есть основная идея a*b = a*2^0*b0 + ... + a*2^n*bn где bi - биты в записи числа b.

А вторая идея это посчитать такие вещи k = (long long)(((long double)a/m)*b) и res = a*b - k*m (m это модуль), бывает что res слегка ошибается и нужно прибавить или отнять m от него, чтобы всё стало корректно

»
15 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится
Во, а кинь ссылку на задачу, если можно. Проверить кое-что хочется.
»
15 лет назад, скрыть # |
 
Проголосовать: нравится +1 Проголосовать: не нравится
Use java, Luke. BigInteger.isProbablePrime(). а если серьезно, то можно сделать это в длинной арифметике быстрее, чем предложенные методы бинарного умножения. быстрее в несколько раз, но надо для этого книги Кнута поизучать, там есть где-то про деление длинного на длинное.
»
11 лет назад, скрыть # |
 
Проголосовать: нравится -21 Проголосовать: не нравится

Бинарное умножение по модулю. binmult(a,b,mod) {

if (b == 1) x == a; else { x = } return x; }

»
11 лет назад, скрыть # |
 
Проголосовать: нравится -21 Проголосовать: не нравится

Бинарное умножение по модулю. Разделяй и властвуй) long long binmultmod(long long a, long long b, long long mod) { long long x; if (a == 0 || b == 0) return 0; if (b==1){ x=a; } else{ x=binmultmod(a, b/2, mod); x=(x+x)%mod; if (b%2==1) x=(x+a)%mod; } return x; }