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

Автор NeverSayNever, 12 лет назад, По-английски

Hello all ,

Hope you all are doing well .

I am looking for an efficient way to multiply two numbers A and B mod C where A,B,C can be in the range [1,1015] .

Here are the list of the solution which i think can think off but there must be some more fast methods .

Solution 1 : simplest and easiest solution is two switch language to jave,python or to use big int in c++ . I don't fill it is a good technique and would like to do it in c .

Solution 2 : Russian Peasant Multiplication


long long int mulmod(long long int a,long long int b) {
    if (M <= 1000000009) return a * b % M;
 
    long long int res = 0;
    while (a > 0) {
        if (a & 1) {
            res += b;
            if (res >= M) res -= M;
        }
        a >>= 1;
        b <<= 1;
        if (b >= M) b -= M;
    }
    return res;
}

which works in O(log(min(A,B))) time .

I heard of karatsuba algorithm which is very fast. Is it faster than the russian multiplication .. can anyone provide me some implementation stuff or some motivation ..

Any kind of help is appreciated :D :D

EDIT1

: Is there any constant time algo exist .

EDIT2

: I also find this .. but i think it is not correct for the values upto 10^18 ..

long long int mulmod(long long int val, long long int n,long long int mod)
{
    long long int q=((double)val*(double)n/(double)mod);
    long long int res=val*n-mod*q;
    res=(res%mod+mod)%mod;
    return res;
}

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

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

You can multiplying strings and after that you can divide result with string C (useing hand-multiplication and division).

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

Karatsuba multiplication is not OK in this case because it have a large constant. It is OK for really big numbers (like 1010000) and it works in . There is also way to multiply two big numbers in with FFT.

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

LL Mul(LL a, LL b, LL M) { LL res = 0; const int k = 14;// floor(64 - log2(MAX_VALUE)) while (a > 0) { int intA = a & ((1 << k) - 1); res = (res + b * intA) % M; a >>= k; b = (b << k) % M; } return res; }
»
12 лет назад, скрыть # |
 
Проголосовать: нравится +13 Проголосовать: не нравится

I guess long double would be better in the third method. And it looks like it works OK for long long.
By the way, why is the second method called "Russian Peasant Multiplication"?
I'd call it binary multiplication as it's practically the same as binary exponentiation.