题目描述
求 a 乘 b 对 p 取模的值,其中 1≤a,b,p≤1018。
输入描述:
第一行a,第二行b,第三行p。
输出描述:
一个整数,表示a×b mod p
的值。
示例1
输入
2
3
9
输出
6
题目链接:https://ac.nowcoder.com/acm/contest/996/C
来源:牛客网
解析
很显然,直接返回a*b%p势必会出现乘法溢出的情况!借鉴快速幂的思想,可以得到如下解决方案:
1.将a*b改为b个a相加,不断对a做"a=a+a"的迭代,可依据b选择对应的迭代值a加入到累加值res中,使得res恰好为初始a值的b倍。
2.由于模运算存在这样一个性质:(a+b)%p=(a%p+b%p)%p。同样可以推广到(a+b+c+…)%p=(a%p+b%p+c%p+…)%p。用文字表述就是任意多个加数相加后再取模等于各加数取模后相加再取模。故只需要每一步都对加数(a+a)取模,每一步都对“各加数取模后相加”得到的(res+a)取模。如此就防止了乘法的溢出,同时快速幂的思想也保证了较低的时间复杂度。
附上之前写的快速幂详解!(通俗易懂),以做对比学习。
AC代码
#include<iostream>
using namespace std;
typedef long long LL;
LL multi(LL a,LL b,LL p){
LL res=0;
while(b>0){
if(b&1) res=(res+a)%p; / /对“各加数取模后相加”得到的(res+a)取模
a=(a+a)%p; / /对加数(a+a)取模
b=b>>1;
}
return res;
}
int main(){
LL a,b,p;
cin>>a>>b>>p;
cout<<multi(a,b,p);
return 0;
}