浅谈 二进制 快速幂以及快速乘法 ʕ •ᴥ•ʔ

世界上有10种人,一种懂二进制,一种不懂二进制;

先谈谈二进制

先看看百度百科怎么说

二进制是计算技术中广泛采用的一种数制二进制数据是用0和1两个数码来表示的数。它的基数为2,进位规则是“逢二进一”,借位规则是“借一当二”,由18世纪德国数理哲学大师莱布尼兹发现。当前的计算机系统使用的基本上是二进制系统,数据在计算机中主要是以补码的形式存储的。计算机中的二进制则是一个非常微小的开关,用“开”来表示1,“关”来表示0。

 定义什么的都不重要,主要是二进制和十进制的转换

二进制转十进制(整数)

先举个栗子:

二进制的101如果转化为十进制是多少呢?

首先,要确立一个思想,也就是在计算机中,大部分都是从0开始计数→所以想知道(101)2是多少,就从右边第一项开始标号:0,1,2;接着就是计算了(101)2=1*2^2+0*2^1+1*2^0=5

附上百度上的栗子:

 好吧,我不得不承认百度讲的比我好。。可是我就是要讲 哈哈~

接下来我们来来谈一谈有关的运算

看到一个博主这几张图挺好的 就转来啦~

个人觉得这几张图已经讲的很清楚了,小弟平时常用 & (按位与) <<(左移) >>(右移)

OK 下面我们聊聊快速幂

普通版:直接暴力(循环)计算这里不再举例了

这样写当然没问题,但是动不动就会超时,因为这样写,时间复杂度大约能达到O(n),虽然看起来也没多大,但是使用快速幂可以把时间复杂度降到O(log₂N)。

int power(int a,int b)// 2^11
{
	int res=1,base=a;//base=2;
	while(b)
	{
		if(b&1)
		res=res*base;
		base=base*base;
		b>>=1;
	}
	//2^11= 2^1 * 2^2 * 2^8
	return res;
}

代码很短,你可以死记。理解记忆更好,以b==11为例,b=>1011,二进制从右向左算,但乘出来的顺序是 a^(2^0)*a^(2^1)*a^(2^3),是从左向右的。我们不断的让base*=base目的即是累乘,以便随时对res做出贡献。

其中要理解base*=base这一步:因为 base*base==base2,下一步再乘,就是base2*base2==base4,然后同理  base4*base4=base8,由此可以做到base-->base2-->base4-->base8-->base16-->base32.......指数正是 2^i ,再看上面的例子,a¹¹= a1*a2*a8,这三项就可以完美解决了,快速幂就是这样。要注意的是指数函数是爆炸式的爆炸式增长,随时就有可能爆范围。

OKK 下面我们来看看快速乘法

在做题的过程中,经常遇到计算a^n,常常采用快速幂来进行求解,但是如果当mod很大的时候在计算x*x的会爆long long.所以我们可以用类似于快速幂的方法把乘法拆分成加法来算

long long mul(long long a,long long b)//快速乘法 
{
	long long res=0;//7*9
	while(b)
	{
		if(b&1)
		res=(res+a)%mod;
		a=(a+a)%mod;
		b>>=1;
	}
	// 9 用二进制表示 1001
	// 7*9= 1*7*1 + 0*7*2 + 0*7*4 + 1*7*8 
	return res;
}
long long power(long long a,long long b)//快速幂 
{
	// 2^11
	long long res=1,base=a;//base=2;
	while(b)
	{
		if(b&1)
		res=mul(res,base)%mod;
		base=mul(base,base)%mod;
		b>>=1;
	}
	//2^11= 2^1 * 2^2 * 2^8
	return res;
}

当时我在学习的时候,看到好多人写快速乘法的时候都写一句把快速幂的 * 改成 + 就行了 但是不知道为什么 今天自己搞懂啦 然后就写上自己对快速乘法一些理解~顺便复习 (学习) 一下二进制 快速幂  嘻嘻~~

猜你喜欢

转载自blog.csdn.net/henucm/article/details/81561012
今日推荐