说实话,本来是不想学这个的,总觉得学了十几年十进制,非要用二进制可变扭了。但是,这个好像是必须得过去的坎,总没道理总是拖着……
然后在进入正题之前,先说一个轻松的话题:
昨天,上c++实验课的时候,有一个学ACM的学长来蹭课,老师检查作业的时候看到学长写了一个:
#define LL long long
然后,老师就问这是什么,学长说,因为懒,所以……blabla
然后老师又问long long是什么……
……
学长很耐心得跟老师解释
(╯‵□′)╯︵┻━┻我在旁边都听不下去了
好了,进入正题:
先谈谈二进制
先看看百度百科怎么说
二进制是计算技术中广泛采用的一种数制。二进制数据是用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(相同颜色代表其相关)
好吧,我不得不承认百度写的还是不错的,就截图放上来吧
二进制转十进制(小数)
(见截图↑)
十进制转二进制
若为整数就是不停地除以二然后取余,若为小数就是乘以二再取整
接下来谈一谈有关运算
--------------------以下内容来自B站某UP主上传的视频-------------------
---------------------------------------以上----------------------------------------
个人认为这个视频已经讲的很清楚了(但是时间久远,我也不记得是哪个了,现在只有PPT还留着//其实是截图……)
好了,做了这么长的铺垫
现在,我们来谈谈快速幂的问题
说到幂函数,当然会联想到cmath头文件下的函数pow(底数,指数),但是如果自己写函数呢?
我想大多数人会跟我一样这么写:
#include <iostream>
using namespace std;
int power(int a,int b)
{
int ans=1;
for(int i=1;i<=b;i++)
{
ans*=a;
}
return ans;
}
int main()
{
int a,b;
int num;
while(cin>>a>>b)
{
num=power(a,b);
cout<<num<<'\n';
}
return 0;
}
这么写当然没有问题,唯一的问题就是——时间复杂度(动不动就TLE还是很绝望的),这样写,时间复杂度大约能达到O(n),虽然看起来也没多大,但是使用快速幂可以把时间复杂度降到O(log₂N)。
核心代码如下:
int power(int a,int b)
{
int r=1,base=a;
while(b!=0)
{
if(b%2) r*=base;
base*=base;
b/=2;
}
return r;
}
顺便引用
快速幂讲解
代码很短,死记也可行,但最好还是理解一下吧,其实也很好理解,以b==11为例,b=>1011,二进制从右向左算,但乘出来的顺序是 a^(2^0)*a^(2^1)*a^(2^3),是从左向右的。我们不断的让base*=base目的即是累乘,以便随时对ans做出贡献。
其中要理解base*=base这一步:因为 base*base==base2,下一步再乘,就是base2*base2==base4,然后同理 base4*base4=base8,由此可以做到base-->base2-->base4-->base8-->base16-->base32.......指数正是 2^i ,再看上面的例子,a¹¹= a1*a2*a8,这三项就可以完美解决了,快速幂就是这样。
顺便啰嗦一句,由于指数函数是爆炸增长的函数,所以很有可能会爆掉int的范围,根据题意选择 long long还是mod某个数自己看着办。