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;
}