快速乘和快速幂

快速幂

快速幂充分利用了二进制的特点(非0即1),把十进制转成二进制表达后再展开,ans对于每一位的当前结果要么乘要么不乘,把原本长度是p的循环变成了长度是p二进制位数(log2(n) )的循环。
举例说明:

已知这样一个事实:

有了它,就可以由前一位二进制幂结果推出后一位二进制幂结果,对于每一位二进制幂结果由0和1决定是否乘于ans(0也可以看做给ans乘上了1)。

如此,长度是11的循环变成了长度是4的循环。

对于p很大的情况,此算法的”快“会充分的体现。

而快速幂取模的算法则因为  的成立,加上取模就能使用
部分转自:https://blog.csdn.net/thearcticocean/article/details/50375115 

代码:

typedef long long LL;
LL power(int a,int p){
	LL ans=1,temp=a;
	while(p){
		if(p&1) ans=ans*temp;
		temp=temp*temp;
		p>>=1;
	}
	return ans;
}

快速乘

简单的讲:求解a*b%c 其中0<a,b,c<2^64

分析:这样的式子和a^b%c很像,所以可以用类似于快速幂取模的方法来做。即,将b写成二进制来看,然后拆开相加(正因为二进制的特殊性,才有快速乘和快速幂的成功,有关快速幂取模可以参考:http://blog.csdn.net/thearcticocean/article/details/50375115):

 

32+16+4=52  (实际操作过程中,每次相加都取模)

这一过程和快速幂取模非常相似。

代码:

LL work(){
    LL ans=0;
    a=a%c;
    b=b%c;
    while(b>0){
        if(b&1) ans=(ans+a)%c;
        a=(a+a)%c;
        b>>=1;
    }
    return ans;
}

例题:

思路:

A+B=C+D

假设A+B=C+D=T

C=(2*A)%T

D=(2*B)%T

k次操作就是

C=(2^k*A)%T

D=(2^k*B)%T

A=min(C,D)

代码如下:

#include<stdio.h>
#include<bits/stdc++.h>
using namespace std;
#define ll long long

ll k=1389472389742429877;
ll a=482333897982347239;
ll b=557432748293424892;
ll t=a+b;
ll mmul(ll a,ll b,ll p){//快速乘(是为了不爆long long 比如long long 乘long long 模P 用快速乘的话就涉及一个long long +long long 这样不会爆始模p后始终都在p以内)
   ll ans=0;
   ll temp=a;
   while(b>0){
    if(b&1)ans=(ans+temp)%p;
    temp=(temp+temp)%p;
    b>>=1;
   }
   return ans%p;
}

ll poww(ll a,ll b,ll p){//快速幂(第一他这里的ans和快速乘不一样,他这里为1,因为他要不断地乘,而快速乘要不断地加,第二,把他这里的乘都换成加就是快速乘了)
 ll temp=a;
 ll ans=1LL;
 while(b>0){
    if(b&1)ans=mmul(ans,temp,p);
    temp=mmul(temp,temp,p);
    b>>=1;
 }
return ans;
}
int main(){
ll l=poww(2,k,t);
ll c=mmul(l,a,t)%t;
ll d=mmul(l,b,t)%t;
printf("%lld\n",min(c,d));
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值