64位整数乘法[CH0102]

本文介绍了一种高效的大数乘法和模运算算法,适用于处理非常大的数值(如10^18级别的整数)。通过快速幂变形和二进制表示,将大数乘法分解为更小的操作,同时利用模运算保持结果在合理范围内,避免了溢出问题。文章提供了两种实现方法,包括直接利用long long类型溢出特性和优化的模运算算法。

题目:求a∗bmod  pa*b\mod pabmodp的值,其中 111aaa,bbb,ppp101810^{18}1018
方法一
快速幂变形,将b用二进制表示,即快速幂变形,将b用二进制表示,即bb=ck−12k−1b=c_{k-1}2^{k-1}b=ck12k1+ck−12k−2c_{k-1}2^{k-2}ck12k2 +.........+c020c_{0}2^{0}c020
a∗b=ck−12k−1∗aa*b=c_{k-1}2^{k-1}*aab=ck12k1a+ck−12k−2∗ac_{k-1}2^{k-2}*ack12k2a +.........+c020∗ac_{0}2^{0}*ac020a
∵a∗2k=(a∗2k−1)∗2∵a*2^{k}=(a*2^{k-1})*2a2k=(a2k1)2;
∴只要观察到ck=1,则ans=ans∗amod  p∴只要观察到c_{k}=1,则ans=ans*a\mod pck=1,ans=ansamodp
每一次位移,都要a=a∗amod  p每一次位移,都要a=a*a\mod pa=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
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值