64位整数乘法[CH0102]

题目:求 a ∗ b m o d    p a*b\mod p abmodp的值,其中 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=ck12k1+ c k − 1 2 k − 2 c_{k-1}2^{k-2} ck12k2 + . . . ... ...+ 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 ab=ck12k1a+ c k − 1 2 k − 2 ∗ a c_{k-1}2^{k-2}*a ck12k2a + . . . ... ...+ c 0 2 0 ∗ a c_{0}2^{0}*a c020a
∵ a ∗ 2 k = ( a ∗ 2 k − 1 ) ∗ 2 ∵a*2^{k}=(a*2^{k-1})*2 a2k=(a2k1)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=ansamodp
每 一 次 位 移 , 都 要 a = a ∗ a m o d    p 每一次位移,都要a=a*a\mod p a=aamodp
代码

#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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值