题目:求
a
∗
b
m
o
d
  
p
a*b\mod p
a∗bmodp的值,其中
1
1
1≤
a
a
a,
b
b
b,
p
p
p≤
1
0
18
10^{18}
1018
方法一
快
速
幂
变
形
,
将
b
用
二
进
制
表
示
,
即
快速幂变形,将b用二进制表示,即
快速幂变形,将b用二进制表示,即
b
=
c
k
−
1
2
k
−
1
b=c_{k-1}2^{k-1}
b=ck−12k−1+
c
k
−
1
2
k
−
2
c_{k-1}2^{k-2}
ck−12k−2 +
.
.
.
...
...+
c
0
2
0
c_{0}2^{0}
c020
则
a
∗
b
=
c
k
−
1
2
k
−
1
∗
a
a*b=c_{k-1}2^{k-1}*a
a∗b=ck−12k−1∗a+
c
k
−
1
2
k
−
2
∗
a
c_{k-1}2^{k-2}*a
ck−12k−2∗a +
.
.
.
...
...+
c
0
2
0
∗
a
c_{0}2^{0}*a
c020∗a
∵
a
∗
2
k
=
(
a
∗
2
k
−
1
)
∗
2
∵a*2^{k}=(a*2^{k-1})*2
∵a∗2k=(a∗2k−1)∗2;
∴
只
要
观
察
到
c
k
=
1
,
则
a
n
s
=
a
n
s
∗
a
m
o
d
  
p
∴只要观察到c_{k}=1,则ans=ans*a\mod p
∴只要观察到ck=1,则ans=ans∗amodp
每
一
次
位
移
,
都
要
a
=
a
∗
a
m
o
d
  
p
每一次位移,都要a=a*a\mod p
每一次位移,都要a=a∗amodp
代码
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ll long long
using namespace std;
ll mul(ll a,ll b,ll p)
{
a%=p;ll ans=0;
while(b)
{
if(b&1)ans=(ans+a)%p;
b>>=1;a=(a<<1)%p;
}
return ans;
}
int main()
{
ll a,b,c;scanf("%lld%lld%lld",&a,&b,&c);
printf("%lld\n",mul(a,b,c));
return 0;
}
方法二
用longlong自然溢出
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
ll mul(ll a,ll b,ll p)
{
a%=p,b%=p;
ll c=(long double)a*b/p;//向下取整
ll ans=(a*b-c*p+p)%p;
return ans;
}
int main()
{
ll a,b,p;scanf("%lld%lld%lld",&a,&b,&p);
printf("%lld\n",mul(a,b,p));
return 0;
}