基础知识
可以把它想成消消乐,两个相同就消掉了。
左移空出来的就补0
右移也是空的补0
技巧
z & -z
实际上是将 z 与 -z 进行按位与操作。这个操作的结果是保留 z 与 -z 二进制表示中共同为 1 的位,而将其他位设为 0。因为 -z 中只有最右边的 1 保持不变,其他位都会被 z 中的相应位设为 0,所以 z & -z
的结果就是 z 二进制表示中最低位的 1 所代表的值。
从右往左数第一个1(最低位)
蓝桥1331
import os
import sys
# 请在此输入您的代码
x = int(input())
ans = 0
for i in range(32):
if (x >> i) & 1 == 1:
ans += 1
print(ans)
蓝桥17021
暴力
def lowbit(z):
return z & -z
def count_combinable_pairs(nums):
count = 0
# 检查每对数字是否满足条件
for i in range(len(nums)):
for j in range(i + 1, len(nums)):
if lowbit(nums[i] + nums[j]) == nums[i] + nums[j]:
count += 1
return count
# 读取输入
N = int(input())
nums = list(map(int, input().split()))
# 计算可结合的元素对的数量并输出结果
print(count_combinable_pairs(nums))
正解
from collections import Counter
n = int(input())
a = list(map(int, input().split()))
# 存储2的次幂 [2, 2 ^ 31]
power = []
x = 2
for i in range(1, 32):
power.append(x)
x = x * 2
# 储存a[j]出现次数
b = Counter()
ans = 0
# 枚举每个数a[i]
for x in a:
# 优化第二重循环:遍历2的次幂
for y in power:
if y - x in b: 前面能有跟他配对的,就加上这个数出现的频率。
ans += b[y - x]
b[x] += 1
print(ans)
蓝桥3691
#区间或运算(思维,前缀和)
import sys
#001 010 011 100 101
#第零位: [1,0,1,0,1]
#第一位: [0,1,1,0,0]
#第二位: [0,0,0,1,1]
from itertools import accumulate
import sys#加速
input=sys.stdin.readline
n,q=map(int,input().split())
a=list(map(int,input().split()))#第零位到第三十位的前缀和
a_bit=[]
for i in range(32):
#求a数组中每个数字的第i位是0还是1
now=[]
for x in a:
now.append((x>>i)&1)
a_bit.append(list(accumulate(now)))
for _ in range(q):
l,r=map(int,input().split())
l,r=l-1,r-1
ans=0
for i in range(32):
#每一位单独考虑,对于第i位而言,只需要判断[l,r]的和是否大于0
if l==0:
t=a_bit[i][r]
else:
t=a_bit[i][r]-a_bit[i][l-1]
if t>0:
ans+=(1<<i)
print(ans)