算法竞赛进阶指南--基本算法之位运算

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

1,我们了解了与、或、非、异或的应用。

2,0x3F3F3F3F是一个特殊的值,整数的两倍不超过0x7F7F7F7F,即int能表示的最大正整数,同时该数的每8位都是相同的。经常memset(a,0x3f,sizeof(a))给数组a赋值0x3F3F3F3F。

3,移位运算:左移:低位补0,高位越界舍弃。左移一位相当于*2;

                       右移:高位以符号位填充,低位越界舍弃。右移一位相当于 /2.0,向下取整。

一、a^b

求a的b次方对p取模的值,其中0≤a,b<2^31,a+b>0 ,  2≤p<2^31。

快速幂算法思路:要求a的b次方这样的幂次方的数,可以直接b的a相乘,但是这样的时间复杂度太大了,会导致超时的可能,所以快速幂的核心思想就是倍增。

例如:求 2^5

首先可以得出:5=1*2^2+0*2^1+1*2^0;  

5的二进制表示数:101。

最重要的是:a^{2^{i}}=(a^{2^{i-1}})^{2}  这句话的意思是每一位二进制位都是前面的数的平方的来的。

所以我们可以用倍增的思想得到数。

 这道题中还有一个需要注意值得关注的点:取模运算

(A+B) mod b=(A mod b+B mod b) mod b

(A+B) mod b=(A mod b+B mod b) mod b

#include<iostream>
using namespace std;
int main()
{
    int a,c,b,p,d;
    cin>>a>>b>>p;
    c=a;d=b;   //记住a,b的值。
    int ans=1%p;
    while(b)
    {
        if(b&1) 
        {
            ans=(long long)ans*a%p;   //如果尾数为1,则将a加入到计算当中
        }
            a=(long long)a*a%p;     //一直要进行倍增
            b>>=1;
    }
   printf("%d^%d mod %d=%d",c,d,p,ans);
  return 0;
}

 

二、64位整数乘法

求a乘b对p取模的值,其中1<=a,b,p<=10^18

这道题可以类似使用快速幂的方法,把整数b用二进制表示,若已求出a*2^i-1 %p,则计算(a*2^i-1)*2 mod p时,运算过程每一步的结果都不超过2*10^18,仍然再64位整数long long 的表示方位内,所以仍然是k次递推求出么每个乘积项。

代码如下:

long long mul(long long a,long long b,long long p)
{ 
   long long ans=0;  
   for(;b;b>>=1)
      {
         if(b&1)  ans=(ans+a)%p;    //把a加入计算结果中
         a=a*2%p;     //这里a倍加
      }
    rerurn ans;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值