位运算

ACM卡常数(各种玄学优化)

旧街凉风 提交于 2020-02-26 21:33:09
首先声明,本博文部分内容仅仅适用于ACM竞赛,并不适用于NOIP与OI竞赛,违规使用可能会遭竞赛处理,请慎重使用!遭遇任何情况都与本人无关哈=7= 我也不想搞得那么严肃的,但真的有些函数在NOIP与OI竞赛中有相关规定不能使用,详细我也不知道各位要了解请自行去找比赛要求咯,当然在ACM竞赛中,没有限制函数,所以所有内容都适用于ACM竞赛。 那么什么是卡常数呢,简单来说就是你和某神犇算法思路一样,结果他的AC了,你的TLE,复杂来说就是程序被卡常数,一般指程序虽然渐进复杂度可以接受,但是由于实现/算法本身的时间常数因子较大,使得无法在OI/ACM等算法竞赛规定的时限内运行结束。 下面就是介绍各种各样的非(花)常(里)实(胡)用(哨)的优化方法的,若本文某些地方有错误或不明确的地方还请指出。=7= 优化I/O 网上有很多说关于cin和scanf的介绍,以及关闭流输入等等优化方法,但这些都还是有可能成为卡常数的地方,那么这个时候,我们就可以自己写输出输出函数了。 下面一个简单的对读入数字的优化: 1 inline void read(int &sum) { 2 char ch = getchar(); 3 int tf = 0; 4 sum = 0; 5 while((ch < '0' || ch > '9') && (ch != '-')) ch = getchar(); 6 tf =

Lecture 10 C语言文件操作

孤人 提交于 2020-02-26 16:48:16
博主不定期更新【 保研/推免、C/C++、5G移动通信、Linux、生活随笔 】系列文章,喜欢的朋友【 点赞+关注 】支持一下吧! 文章目录 Lecture 10 文件 1. 文件 1.1 格式化输入输出 1.2 文件输入输出 1.3 二进制文件 2. 位运算 2.1 按位运算 2.2 移位运算 2.3 位运算例子 2.4 位段 Lecture 10 文件 1. 文件 1.1 格式化输入输出 printf %[flags][width][.prec][hlL]type Flag 含义 - 左对齐 + 在前面放+或- (space) 整数留空 0 0填充 width或prec 含义 number 最小字符数(输出宽度) * 下一个参数是字符数 .number 小数点后的位数 .* 下一个参数是小数点后的位数 类型修饰 含义 hh 单个字节(char) h short l long ll long long L long double type 用于 type 用于 i或d int g float u unsignde int G float o 八进制 a或A 十六进制浮点 x 十六进制 c char X 字母大写的十六进制 s 字符串 f或F float,6 p 指针 e或E 指数 n 到目前为止 读入/写出的个数 # include <stdio.h> int main ( )

Java千问:Java位运算经典应用(二)

一笑奈何 提交于 2020-02-25 23:30:50
接上篇 三、不借助中间变量交换两个变量的值 通常情况下,我们要交换两个变量的值都按如下步骤操作: 这种操作方式不难理解,实现交换变量值的关键点就在于中间变量c。而现在的题目要求是不借助中间变量来交换a和b的值。如果不使用位运算的方式,同样可以做到不借助中间变量交换两个变量的值,其实现过程如下。 为了讲解方便,我们把最初a与b的值称之为原始a和原始b,3行代码就是3步操作: 第1步:把原始a与原始b相加的和存储到变量a中,变量b的值暂时没有发生变化。 第2步:用这个和减去原始b,再赋值到变量b中,经过这一步运算,变量b中就保存了原始a的值。 第3步:用原始a、b之和减去原始a的值,就得到原始b,并且把这个值保存到变量a中。 通过以上3步就实现了a、b两个变量在不借助中间变量的情况下进行值的交换。这种算法虽然没有借助中间变量,但有一个问题是如果a和b都是较大的数,在做第1步操作的时候就有可能出现两值相加的和超出int类型的最大值,产生溢出的现象,从而导致后面的运算全部出错。 而我们用位运算的方式实现交换,就不存在这个问题了。具体代码如下: 讲述这段代码之前,先回顾一个运算规律,那就是: a^b^b的运算结果等于a 。对此运算规律有疑义,请阅读《 Java千问:Java语言位运算符详解 》一文。为了表述方便,我们把a^b的操作称之为”用b对a加密”,之所以这么称呼

Java千问:Java位运算经典应用(一)

天大地大妈咪最大 提交于 2020-02-25 22:45:56
很多人认为位运算在实际开发过程中并没什么用,学习位运算也只是为了应付面试。这种想法是错误的,接下来我们就通过几篇连载文章介绍一下位运算在实际开发过程中的几个经典应用实例。如果对位运算规则掌握还不是很熟练,可以先阅读《 Java千问:Java语言位运算符详解 》。这篇文章不仅详细讲解了Java位运算的基本规则和一些常用的运算定律,同时还在文中提到了一些常用的位运算实际应用,比如可以用位运算操作的方式快速把某个变量所在的内存单元清零,或者位运算的方式实现某个变量快速倍增等等。但文中所这提到的这几个实际应用比较简单,本次连载文章将为大家讲述的是更加复杂和实际的应用经典案例。此外,为获得更好的阅读效果,请各位读者在读本文之前先熟练掌握”补码”的计算规则。 一、判断整数的奇偶性 按照传统的思路,判断一个整数的奇偶性是通过用这个数与2求模,看运算结果是否为0。学了位运算符以后,我们可以换一种思路来考虑问题。我们知道:Java语言中,所有数字存储在内存中,都要先转换成补码的形式。任何一个偶数用补码表示出来后,它的最后一个二进制位都是0,而奇数补码的最后一个二进制位都是1。所以,我们可以通过判断这个整数的补码的最后一位二进制数是0还是1,来判断这个数是偶数还是奇数。判断的方法就是用这个数与1进行按位与的操作,如果结果为0,那么这个数就是偶数,否则就是奇数。如果大家不理解这个算法的原理,请看下图:

位运算

时光总嘲笑我的痴心妄想 提交于 2020-02-21 22:23:12
文章目录 一、进制表示 1、进制 2、进制的表现形式 3、原码、反码和补码 二、位运算 1、&——与运算(and) (1)运算规则 (2)应用 2、|——或运算(or) (1)运算规则 (2)应用 3、^——异或运算 (xor) (1)运算规则 (2)应用 4、~——非运算(not) (1)运算规则 三、移位运算 1、<<——左移运算 2、>>——右移运算 3、>>>——无符号右移运算(没有无符号左移运算) 四、位运算应用 1、判断奇偶数(与运算) 2、交换两个数(异或) 3、求 m 的 n 次方 4、找出不大于 N 的最大的 2 的幂指数 一、进制表示 1、进制 进制是一种记数方式 ,可以用有限的数字符号代表所有的数值。由特定的数值组成。 2、进制的表现形式 二进制: 由 0 和 1 两个数字组成,都是以 0b 开始; 八进制: 由 0~7 数字组成,为了区分于其他进制的数字,都是以 0 开始; 十进制: 都是以 0~9 这九个数字组成,不能以 0 开头; 十六进制:由 0 ~ 9 和 A~ F 组成,为了区分于其他进制的数字,都是以 0x 或 0X 开始。 3、原码、反码和补码 原码——即为计算机中对数值的二进制表示 。如,十进制的 5 用二进制表示为 0000 0101 ;(最高位为符号位,1 表示负,0 表示正,并且在原、反、补的转换中,符号位不变) 反码 ——即取反

位运算---2、3、4的幂

一世执手 提交于 2020-02-21 19:15:40
2的幂——即数字按位展开只有一位为1,所以 num&(num - 1) ==0; return (n>0)&&((n&(n-1))==0) 4的幂——相较于2的幂而言对二进制位要求更高,不仅要求数字按位展开只有一位为1,且1的后面必须有偶数个0,即…00000100,…00010000,…01000000。 法一: (num-1)后必然是三的倍数: return ((num & (num - 1)) == 0) && ((num - 1) % 3 == 0); 法二,既然已规定32位,那么只有将所有的4的幂的位置上置1——即0x…101010101010101(0x55555555)与num相与为num本身即可; return (num >0)&&((num & (num - 1)) == 0) && ((num & 0x55555555) == num); 法三:由幂的定义出发:利用换低公式 x = log4(num )(以4为底),x为整数即可。 return (num > 0) && (Math.ceil(Math.log10(num) / Math.log10(4)) - Math.log10(num) / Math.log10(4) == 0); 3的幂——由幂的定义出发:利用换低公式x = log3(num )(以3为底),x为整数即可;或者Math.pow(log3

利用位运算消除二进制最后一个1,计算二进制中1的个数

佐手、 提交于 2020-02-21 01:56:21
这几天刷leetcode学习了一个新知识,利用位运算来消除二进制的最后一个1,进一步还可以计算一个二进制有多少个1 假设一个n = 01101010,我们把它减一即n-1 = 01101001,然后再将它们相与result = n&(n-1) = 01101000,就可以把最后一个1消除了,原理也很简单,n-1的话,会一直向前寻找可借的位,从而跳过低位连续的0,而向最低位的1借位,借位后最低位的1变为0,原先最低位1的下一位从0变为1,其余位都不变,相与之后其它位不变,1(最低位1)0 &01(n-1对应的位)= 00,从而消除最低位的1。 利用这个原理计算二进制中1的个数 int countOne(int n){ int res = 0; while(n!=0){ res++; n = n&(n-1); } return res; } 来源: CSDN 作者: vegeticken 链接: https://blog.csdn.net/weixin_41506373/article/details/104412138

位运算

别来无恙 提交于 2020-02-20 10:23:11
1.位运算概述 从现代计算机中所有的数据二进制的形式存储在设备中。即0、1两种状态,计算机对二进制数据进行的运算(+、-、*、/)都是叫位运算,即将符号位共同参与运算的运算。 口说无凭,举一个简单的例子来看下CPU是如何进行计算的,比如这行代码: int a = 35; int b = 47; int c = a + b; 计算两个数的和,因为在计算机中都是以二进制来进行运算,所以上面我们所给的int变量会在机器内部先转换为二进制在进行相加: 35: 0 0 1 0 0 0 1 1 47: 0 0 1 0 1 1 1 1 ———————————————————— 82: 0 1 0 1 0 0 1 0 所以,相比在代码中直接使用(+、-、*、/)运算符,合理的运用位运算更能显著提高代码在机器上的执行效率。 2.位运算概览[td] 符号 描述 运算规则 & 与 两个位都为1时,结果才为1 | 或 两个位都为0时,结果才为0 ^ 异或 两个位相同为0,相异为1 ~ 取反 0变1,1变0 << 左移 各二进位全部左移若干位,高位丢弃,低位补0 >> 右移 各二进位全部右移若干位,对无符号数,高位补0,有符号数,各编译器处理方法不一样,有的补符号位(算术右移),有的补0(逻辑右移) 3.按位与运算符(&) # 定义:参加运算的两个数据,按二进制位进行“与”运算。 运算规则: 0&0=0 0

位运算

北慕城南 提交于 2020-02-20 10:07:16
1.位运算概述 从现代计算机中所有的数据二进制的形式存储在设备中。即0、1两种状态,计算机对二进制数据进行的运算(+、-、*、/)都是叫位运算,即将符号位共同参与运算的运算。 口说无凭,举一个简单的例子来看下CPU是如何进行计算的,比如这行代码: int a = 35; int b = 47; int c = a + b; 计算两个数的和,因为在计算机中都是以二进制来进行运算,所以上面我们所给的int变量会在机器内部先转换为二进制在进行相加: 35: 0 0 1 0 0 0 1 1 47: 0 0 1 0 1 1 1 1 ———————————————————— 82: 0 1 0 1 0 0 1 0 所以,相比在代码中直接使用(+、-、*、/)运算符,合理的运用位运算更能显著提高代码在机器上的执行效率。 2.位运算概览 [td] 符号 描述 运算规则 & 与 两个位都为1时,结果才为1 | 或 两个位都为0时,结果才为0 ^ 异或 两个位相同为0,相异为1 ~ 取反 0变1,1变0 << 左移 各二进位全部左移若干位,高位丢弃,低位补0 >> 右移 各二进位全部右移若干位,对无符号数,高位补0,有符号数,各编译器处理方法不一样,有的补符号位(算术右移),有的补0(逻辑右移) 3.按位与运算符(&) # 定义:参加运算的两个数据,按二进制位进行“与”运算。 运算规则: 0&0=0

你真的搞清位运算了么?以Java为例总结

≯℡__Kan透↙ 提交于 2020-02-16 00:05:43
二进制位运算是最贴近计算机真实运算操作,通过位运算,我们可以高效的完成各种基础运算(加减乘除取余等),我们还可以使用位运算巧妙的完成原本很复杂的工作,真正理解计算机,我们才能更好的使用计算机。我将通过基础理解开始,讲解到Java中的一些实际应用。本场Chat中,将学到一下内容 •对原码、反码、补码等基础进行重拾 •与或异或移位等正负数运算细节 •正负数位运算的操作 写在前面 二进制位运算是最贴近计算机真实运算操作,通过位运算,我们可以高效的完成各种基础运算(加减乘除取余等),我们还可以使用位运算巧妙的完成原本很复杂的工作,真正理解计算机,我们才能更好的使用计算机。在这一片文章,我将通过基础理解开始,讲解到 Java 中的一些实际应用。 机器数和机器数的真值 一个数在计算机中的二进制表示形式,叫做这个数的机器数。机器数是带符号的,在计算机用机器数的最高位存放符号,正数为 0,负数为 1。举个例子,比如在机器字长为 8 位的情况下(机器字长是指计算机直接处理的二进制数据的位数,它决定了计算机的运算精度,一般是 8 的整数倍,8 位、16 位、32 位、64 位、128 位),十进制中的+3,转换成二进制就是 0000 0011,如果是-3,转换成二进制就是 1000 0011。转换的二进制数 0000 0011 和 1000 0011 就是机器数。 这里我们还需要知道的就是机器数的真值