64位整数乘法

  题目大意:给定两数a,b和模数p,求a*b mod p的值。

解法一:迭代累加法

  用类似于快速幂的思想,我们把a*b看作b个a相加,每次将各项两两合并,然后令b除以2。特判b不是2的倍数时把单独的一项累积到答案上。复杂度为对数级别。

代码:

  1. #include <cstdio>  
  2. #include <iostream>  
  3. #include <cstring>  
  4. using namespace std;  
  5. long long p, a, b;   
  6. long long pro(long long a, long long b, const long long &p) {  
  7.     long long ans = 0;  
  8.     while (b) {  
  9.         if (b & 1)  
  10.             ans = (ans + a) % p;  
  11.         b >>= 1;  
  12.         a = (a << 1) % p;  
  13.     }  
  14.     return ans;  
  15. }  
  16. int main() {  
  17.     cin >> a >> b >> p;  
  18.     cout << pro(a, b, p);  
  19.     return 0;  
  20. }  

解法二:转化原式后O(1)求解

  这个方法我想了好久才明白……首先,在c++中,除法是比乘法优先的。算法进阶上给出的程序并没有说明这点。

  我们考虑模运算的数学定义:

  a * b % p = a * b - [(a * b) / p] * p = a * b - [a * (b / p)] * p

  其中a * (b/p)显然可以用long double型存下来,并且能够保证除法的精度。(long double 的精度由编译器决定,一般情况下可以存18 ~ 19位)那么我们可以先计算出上式中的两项,然后作差即可得到答案。因为二者的差小于模数p,差值一定在long long范围中,可以不用考虑高位上的溢出。

代码:

  1. #include <cstdio>  
  2. #include <iostream>  
  3. #include <cstring>  
  4. using namespace std;  
  5. long long a, b, p;  
  6. long long mul(long long a, long long b) {  
  7.     a %= p, b %= p;   
  8.     long long t2 = (long double)(a * b) / p;  
  9.     long long del = a * b - t2 * p;  
  10.     del += p, del %= p;  
  11.     return del;  
  12. }  
  13. int main() {  
  14.     cin >> a >> b >> p;  
  15.     cout << mul(a, b);  
  16.     return 0;  
  17. }  
原文地址:https://www.cnblogs.com/TY02/p/11240048.html