一个小问题

问题描述

设机器字长 w w w比特, u ∣ w , w = u c u|w,w = uc uw,w=uc。将 w w w分为 c c c个连续长度为 u u u比特的区间,称为 u u u区间。实现操作:对于一个机器字 x x x,如果一个 u u u区间非0,则将区间最右bit置1,其余为0。要求算法时间为 O ( 1 ) O(1) O(1)

思路

考虑异或操作。对于一个 u u u位的二进制数 x x x,当且仅当 x = 0 x = 0 x=0的时候, f ( x ) = ( ( N O T ( x ) ) + 1 ) f(x) = ((NOT(x))+1) f(x)=((NOT(x))+1)会向第u+1位进位。其中 N O T ( x ) NOT(x) NOT(x)表示对 x x x取反
于是,当 c = 1 c=1 c=1的时候,即 u u u区间就是字长时,通过执行 f ( x ) f(x) f(x) C F CF CF位是否为1,可判断 x x x是否为0。
但是,当 c > 1 c>1 c>1时,我们就必须考虑上述的“进位操作”能否正常的保存下来,以便于我们判零。
不妨先考虑 c = 2 c=2 c=2时的情况,设高地址的 u u u区间为 x x x,低地址的 u u u区间为 y y y
y y y不产生进位,我们就无需考虑进位之后的问题;
y y y产生了进位,那么什么时候这种进位可以在 x x x的最低位保存下来呢?显然是 x x x的最低位为0时(取反再加1后,该位为0)。
如果 x x x的最低位不为零怎么办?我们可以先处理它,得到最低位对答案的贡献,记为 a n s 1 ans_1 ans1。然后将最低位统统清零,再通过 f ( x ) f(x) f(x)来判零。记此时的答案为 a n s 2 ans_2 ans2
可是又产生了一个新的问题:如果一个区间的值就是00…01,在最低位清零之后, f ( x ) f(x) f(x)判零法会失效。怎么办?
我们先枚举某个区间在两次答案中的所有可能情况 S S S={(零,非零),(零,零),(非零,零),(非零,非零)}
首先,(零,非零)不会出现,可以直接排除;
其次,对于(零,零) 和 (非零,非零),判零法是有效的;
最后,出现(非零,零),说明判零法失效,我们需要消除这种影响。
对于 c > 2 c>2 c>2的情况可以直接推广。

过程

分析完解题思路后,假设我们得到的 w w w位二进制数是 x x x
我们如何来得到 a n s 1 ans_1 ans1呢?
x x x按位与一个二进制常数 c 1 = ( ( 0 ) u − 1 1 ) c ( 2 ) c_1={((0)^{u-1}1)^c}_{(2)} c1=((0)u11)c(2),( i i i k k k次幂表示连续的 k k k i i i
常数中的1用来“保存”我们需要的位,如果那一位是1,则会被记录到 a n s 1 ans_1 ans1的相应位中,否则就不会被记录下来。
之后,如何消除最低位呢?
x x x按位与一个二进制常数 c 2 = ( ( 1 ) u − 1 0 ) c ( 2 ) c_2={((1)^{u-1}0)^c}_{(2)} c2=((1)u10)c(2),并替换 x x x
此时,常数中的0负责对相应的位清零
再然后,对 f ( x ) f(x) f(x)的结果右移 u u u位就可以得到 a n s 2 ans_2 ans2
注:最高位的进位(如果有),保存在CF中,需要采用带进位循环右移一位取出CF到最高位,之后再采用逻辑右移对最高位补零

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值