题目大意:给定两数a,b和模数p,求a*b mod p的值。
解法一:迭代累加法
用类似于快速幂的思想,我们把a*b看作b个a相加,每次将各项两两合并,然后令b除以2。特判b不是2的倍数时把单独的一项累积到答案上。复杂度为对数级别。
代码:
- #include <cstdio>
- #include <iostream>
- #include <cstring>
- using namespace std;
- long long p, a, b;
- long long pro(long long a, long long b, const long long &p) {
- long long ans = 0;
- while (b) {
- if (b & 1)
- ans = (ans + a) % p;
- b >>= 1;
- a = (a << 1) % p;
- }
- return ans;
- }
- int main() {
- cin >> a >> b >> p;
- cout << pro(a, b, p);
- return 0;
- }
解法二:转化原式后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范围中,可以不用考虑高位上的溢出。
代码:
- #include <cstdio>
- #include <iostream>
- #include <cstring>
- using namespace std;
- long long a, b, p;
- long long mul(long long a, long long b) {
- a %= p, b %= p;
- long long t2 = (long double)(a * b) / p;
- long long del = a * b - t2 * p;
- del += p, del %= p;
- return del;
- }
- int main() {
- cin >> a >> b >> p;
- cout << mul(a, b);
- return 0;
- }