版权声明:本文为博主原创作品, 转载请注明出处! https://blog.csdn.net/solider98/article/details/83210436
思路分析:给出两种方法, 法1基于递推, 法2利用C++基本数据类型的性质
法1:
考虑b的二进制表示, (a * b) mod p = (a * ()) mod p = () mod p
又: , 则可先求出s = , 且s < p <= , 可直接使用语句: s * 2 % p 计算
至此,首先计算, 然后递推即可, AC代码如下:
//CH0102_64位整数乘法
#include <iostream>
#include <cstdio>
using namespace std;
//返回(a * b) mod p的值, 要求:1 <= a, b, p <= 10^18
long long getVal(long long a, long long b, long long p){
long long ans = 0, tmp = a % p;
for(; b; b >>= 1, tmp = tmp * 2 % p) if(b & 1) ans = (ans + tmp) % p;
return ans;
}
int main(){
long long a, b, p;
scanf("%lld %lld %lld", &a, &b, &p);
cout << getVal(a, b, p) << endl;
return 0;
}
法2:
由 (a * b) mod p = a * b - , 且该等式两端的值小于, 可先计算的值, 如何计算s? 考虑到s <= , 利用C++中long double的有效数字为18~19位, 因此对a, b, p使用long double计算a * b / p的值, 对结果取整数部分即为s的值.继而将a, b, s, p均定义为unsigned long long 类型, 依据C++中unsigned long long运算性质, 表达式a * b - s * p的值为其数学上的实际值对取模, 因为其实际值小于, 故表达式a * b - s * p 为其实际值, 具体步骤如下AC代码所示:
//CH0102_64位整数乘法
#include <iostream>
#include <cstdio>
using namespace std;
typedef unsigned long long ull;
//返回(a * b) mod p的值, 要求:1 <= a, b, p <= 10^18
ull getVal(ull a, ull b, ull p){
return a * b - (ull)((long double)a * b / p) * p;
}
int main(){
long long a, b, p;
scanf("%lld %lld %lld", &a, &b, &p);
cout << getVal(a, b, p);
return 0;
}