【题解】Acwing 90 64位整数乘法

64位整数乘法

题目传送门

求 a 乘 b 对 p 取模的值。

输入格式

第一行输入整数a,第二行输入整数b,第三行输入整数p。

输出格式

输出一个整数,表示a*b mod p的值。

数据范围

1≤a,b,p≤1018

输入样例:

3
4
5

输出样例:

2

思路说明:

解法一:

类快速幂写法。
可以参看a ^ b的思路说明

代码展示:

#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;typedef unsigned long long ull;

ll a,b,p;
ll mul(ll a,ll b,ll p){
    ll ans = 0,ttt = a;
    while(b>0){
        if(b&1) ans = (ans+ttt) % p;
        ttt = (ttt<<1) % p;
        b >>= 1;
    }
    return ans;
}

int main(){
    scanf("%lld%lld%lld", &a, &b, &p);
    printf("%lld
", mul(a,b,p));
    return 0;
}

解法二:

思路说明:

主要利用

a * b mod p = a * b - (lfloor)a * b / p( floor) * p

当M大于a * b时,a * b % p = a * b % M % p

这里的强制转化就是这样一个对一个大数取模的过程。

注意考虑浮点数的精度误差。

书上有些地方使用ull,在题目指定范围内,ll应当也是能达到同样效果

一些细节将会在代码的注释中说明。

时间复杂度 O(1)

代码展示:

#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;typedef unsigned long long ull;
typedef long double ld;

ll a,b,p;

ll mul(ll a,ll b,ll p){
    a %= p, b %= p; // 确保 a 和 b 在0 ~ p之间
	ll c = (ld)a * b / p; 
	ll x = a * b, y = c * p;
	ll ans = (ll)(x % p) - (ll)(y % p);
	if(ans < 0) ans += p; // 强制转化可能使c变小了
	return ans;
}

int main(){
    scanf("%lld%lld%lld", &a, &b, &p);
    printf("%lld
", mul(a,b,p));
    return 0;
}
原文地址:https://www.cnblogs.com/RemnantDreammm/p/14126216.html