快速幂
倘如我们要算
a
b
a^b
ab,平常只能想到跑一个for循环,一个一个的累乘。然而我们可以利用二进制的思想将b拆开。例:b为11,可拆成
(
2
3
+
2
1
+
2
0
)
(2^3+2^1+2^0)
(23+21+20)
这样
a
b
a^b
ab就等于
a
2
3
∗
a
2
1
∗
a
2
0
a^{2^3}*a^{2^1}*a^{2^0}
a23∗a21∗a20
然后我们可以跑一个while,在b的二进制为一的位上乘上相应的a的幂即为答案。
int quick_pow(int a, int b, int mod)//快速幂
{
int c = 1;//记录答案
while(b)
{
if(b & 1)//如果当前位为1,即将a的幂乘入答案
c = c * a % mod;//有的题目要取模
a = a * a % mod;//让a的幂的指数翻倍,对应b的二进制
b >>= 1;
}
return c;
}
快速乘
跟快速幂同样的思想。我们有
a
∗
b
a*b
a∗b,正常计算耗时慢还可能溢出,所以我们可以使用快速乘。若b是11,我们将b拆成
(
2
3
+
2
1
+
2
0
)
(2^3+2^1+2^0)
(23+21+20),那么
a
∗
b
a*b
a∗b为:
(
a
∗
2
3
+
a
∗
2
1
+
a
∗
2
0
)
(a*2^3+a*2^1+a*2^0)
(a∗23+a∗21+a∗20),同样道理,我们在b的二进制为一的位上加上a的倍数就行。
int quick_mult(int a, int b, int mod)//快速乘
{
int c = 0;//记录答案
while(b)
{
if(b & 1)//b对应的二进制中为一的位
c = (c + a) % mod;//取模,防止溢出
a = (a + a) % mod;//让a翻倍,对应b的二进制
b >>= 1;
}
return c;
}
用异或计算求和问题
异或操作,比较二进制中对应的位,同0异1。也叫xor。
我们知道,如果不同位为1且相同位为0,其实相当于两个数求和,但不进位。即不进位的加法。那我们如何用异或来进行进位加法呢。可以用到&。用&来算出两个数的相同位,然后左移一位表示进位之后的结果。剩下的也就是算(a^b)+(a&b)。我们可以在这里进行递归,直到b为0时,加无可加。解释递归。
int Xor_Add(int num1, int num2)//异或求和
{
if(num2 == 0)
return num1;
int a = num1 ^ num2;//进行不进位的加法
int b = num1 & num2;//保存相同的位
b <<= 1;//左移进位
return Add(a, b);
}