Advertisement
karbaev

peasant

Oct 10th, 2015
159
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.55 KB | None | 0 0
  1. //1. Упрощенный вариант
  2. static int MulPeasant(int a, int b, int n)
  3. {
  4.     b  = b  % n; // не нужно, если гарантированно b  < n
  5.     a  = a  % n; // не нужно, если гарантированно a  < n
  6.     int acc = 0;
  7.     while (a > 0)
  8.     {
  9.         if ((a & 1) != 0)
  10.             acc = (acc + b) % n;
  11.         b  = (b * 2) % n;
  12.         a  >>= 1;
  13.     }
  14.     return acc;
  15. }
  16. /*Выражение (acc + b  * b) % n — инвариант цикла.
  17. Должно работать, если n < MAXINT/2.
  18. */
  19.  
  20.  
  21. //2. Полный вариант
  22. //Для случая произвольного n подойдёт небольшая модификация:
  23. static int MulPeasant(int a, int b, int n)
  24. {
  25.     b  = b  % n; // не нужно, если гарантированно b  < n
  26.     a  = a  % n; // не нужно, если гарантированно a  < n
  27.     int acc = 0;
  28.     while (a > 0)
  29.     {
  30.         if ((a & 1) != 0)
  31.             acc = SafeAdd(acc, b, n);
  32.         b  = SafeAdd(b, b, n);
  33.         a  >>= 1;
  34.     }
  35.     return acc;
  36. }
  37.  
  38. static int SafeAdd(int x, int y, int n)
  39. {
  40.     if (x <= MAXINT - y) // проверка на переполнение сложения
  41.     {
  42.         int result = x + y; // x, y < n, x + y < 2n. (x + y) mod n равно или x + y,
  43.         return (result >= n) ? (result - n) : result;  // или x + y - n
  44.     }
  45.     else // в этом случае x + y > MAXINT >= n, но x + y < n + n = 2n
  46.     {    // значит (x + y) mod n = x + y - n
  47.         return x - (n - y); // n - y > 0, вычитаем два положительных числа меньших n
  48.     }
  49. }
  50.  
  51. //Можно ещё организовать поразрядное умножение:
  52. const int halfbits = sizeof(int) * 8 / 2;
  53. const int halfbase = (1 << halfbits);
  54. const int lomask = halfbase - 1;
  55.  
  56. static int MulDigits(int a, int b, int n)
  57. {
  58.     int reducedbase = halfbase % n;
  59.     int reducedbasesquare = (reducedbase * reducedbase) % n;
  60.     int ah = a  >> halfbits, al = b & lomask;
  61.     int bh = b >> halfbits, bl = a & lomask;
  62.  
  63.     int ll = (al * bl) % n,
  64.         lh = (((ah * bl) % n) * reducedbase) % n,
  65.         hl = (((al * bh) % n) * reducedbase) % n,
  66.         hh = (((ah * bh) % n) * reducedbasesquare) % n;
  67.     return SafeAdd(
  68.                SafeAdd(ll, lh, n),
  69.                SafeAdd(hl, hh, n),
  70.                n);
  71. }
  72. //(Если ваше n одно и то же всё время, константы reducedbase и reducedbasesquare можно предвычислять.)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement