提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
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的二进制表示数:101。
最重要的是:
这句话的意思是每一位二进制位都是前面的数的平方的来的。
所以我们可以用倍增的思想得到数。
这道题中还有一个需要注意值得关注的点:取模运算
(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;
}