C++——快速幂&二进制

说实话,本来是不想学这个的,总觉得学了十几年十进制,非要用二进制可变扭了。但是,这个好像是必须得过去的坎,总没道理总是拖着……

然后在进入正题之前,先说一个轻松的话题:

昨天,上c++实验课的时候,有一个学ACM的学长来蹭课,老师检查作业的时候看到学长写了一个:

#define LL long long

然后,老师就问这是什么,学长说,因为懒,所以……blabla

然后老师又问long long是什么……

……

学长很耐心得跟老师解释

(╯‵□′)╯︵┻━┻我在旁边都听不下去了


好了,进入正题:

先谈谈二进制

先看看百度百科怎么说

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


定义什么的都不重要,主要是二进制和十进制的转换//这个考试是会考的……

二进制转十进制(整数)

先举个栗子:

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

首先,要确立一个思想,也就是在计算机中,大部分都是从0开始计数→所以想知道(101)2是多少,就从右边第一项开始标号:012;接着就是计算了(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某个数自己看着办。


  • 17
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
快速读取超大二进制文件是一个在处理大据量时非常重要的问题。以下是一些方法和技巧可以帮助我们有效地读取超大二进制文件。 1. 使用适当的文件读取模式:在打开文件时,使用二进制模式("rb")而不是文本模式。二进制模式可以减少不必要的转换和编码。 2. 使用缓冲区读取:将文件读取操作与适当大小的缓冲区(buffer)结合使用,可以减少磁盘I/O次,提高读取速度。通常,一个较大的缓冲区大小(例如64KB或更大)是高效读取的关键。 3. 使用内存映射:对于特别大的文件,使用内存映射技术可以将文件的一部分映射到内存中,从而直接在内存中进行访问,而不需要频繁的磁盘I/O。这可以大大提高读取速度。 4. 分块读取:对于超大文件,可以将文件分成较小的块(例如1MB或更小),逐块读取、处理和释放内存。这样可以减少内存的使用,避免因为文件过大而导致内存不足的问题。 5. 并行读取:如果计算机具有多个处理器或核心,可以考虑使用并行读取技术,将文件划分为多个部分,同时在不同的处理器或核心上进行读取。这可以有效地利用多核资源,提高读取速度。 总之,要快速读取超大二进制文件,我们需要使用适当的文件读取模式、缓冲区读取、内存映射、分块读取和并行读取等技巧。这些方法可以大大提高读取速度,提升对大据量的处理效率。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值