【题单】位运算(基础/性质/拆位/试填/恒等式/贪心/脑筋急转弯)
来源: 分享丨【题单】位运算(基础/性质/拆位/试填/恒等式/贪心/脑筋急转弯)
前置知识: 分享|从集合论到位运算,常见位运算技巧分类总结!
创建题单的原因: 容斥原理 划分型 DP【力扣周赛 393】 的Q3 我直接被秒杀!, Q4也是位运算(我看都没有看); 因此学习位运算十分有必要!
3315. 构造最小位运算数组 II (lowbit)
基础题
- 1486. 数组异或操作 1181
- 2595. 奇偶位数 1207
- 231. 2 的幂
- 342. 4的幂
- 476. 数字的补数 1235
- 191. 位1的个数
- 338. 比特位计数 也可以 DP
- 1356. 根据数字二进制下 1 的数目排序 1258
- 461. 汉明距离
- 2220. 转换数字的最少位翻转次数 1282
- 868. 二进制间距 1307 (模拟 / 双指针)
- 2917. 找出数组中的 K-or 值 1389
- 693. 交替位二进制数
与或(AND/OR)的性质
- 2980. 检查按位或是否存在尾随零 1234
- 1318. 或运算的最小翻转次数 1383
- 2419. 按位与最大的最长子数组 1496 (脑筋急转弯(
&
的性质)) - 2871. 将数组分割成最多数目的子数组 1750
- 2401. 最长优雅子数组 1750
- 2680. 最大或值 额外空间
- 2411. 按位或最大的最小子数组长度 1938
- 898. 子数组按位或操作 2133
- 1521. 找到最接近目标值的函数值 2384
异或(XOR)的性质
- 1720. 解码异或后的数组 1284
- 2433. 找出前缀异或的原始数组 1367 (前缀异或和差分复原)
- 1310. 子数组异或查询 1460 (前缀异或和/树状数组)
- 2683. 相邻值的按位异或 1518
- 1829. 每个查询的最大异或值 1523
- 2997. 使数组异或和等于 K 的最少操作次数 1525
- 1442. 形成两个异或相等数组的三元组数目 1525 (前缀和 + 哈希表 => o(n))
- 2429 最小异或 1532
- 2527. 查询数组异或美丽值 1550 (orz)
- 2317. 操作后的最大异或和 1679
- 2588. 统计美丽子数组数目 1697 (固定套路! 学会转换!)
- 2564. 子字符串异或查询 1959
- 1734. 解码异或后的排列 2024
- 2857. 统计距离为 k 的点对 2082
拆位 / 贡献法
- 477. 汉明距离总和
- 1863. 找出所有子集的异或总和再求和 可以做到 时间 (看不懂思密达)
- 2425. 所有数对的异或和 1622 可以做到 时间
- 2275. 按位与结果大于零的最长组合 1642
- 1835. 所有数对按位与结果的异或和 1825 也有恒等式做法
- 2505. 所有子序列和的按位或(会员题)
LogTrick 技巧
LogTrick: 问一个数组的所有子数组的元素 AND/OR/lcm/gcd 的值为 k (或者是某个可能含有子数组的表达式的值) 的最近元素/子数组个数(二分
right-left
/三分(滑窗))LogTrick利用AND/OR/lcm/gcd的性质, 使得时间复杂度为
视频讲解可以看周赛400 Q4
: Q4-3171. 找到按位或最接近 K 的子数组
-
额外维护一个数组: 利用或运算的性质 + 通用模板(Python/Java/C++/Go)
-
2411. 按位或最大的最小子数组长度 1938
-
3209. 子数组按位与值为 K 的数目 ~2100
-
1521. 找到最接近目标值的函数值 2384 做法同 3171 题
试填法
- 3007. 价值和小于等于 K 的最大数字 2258
- 421. 数组中两个数的最大异或值,试填法题解
- 2935. 找出强数对的最大异或值 II 2349
- 3022. 给定操作次数内使剩余元素的或值最小 2918
恒等式
- 1835. 所有数对按位与结果的异或和 1825
- 2354. 优质数对的数目 2076
思维题(贪心、脑筋急转弯等)
- 2546. 执行逐位运算使字符串相等 1605
- 1558. 得到目标数组的最少函数调用次数 1637
- 2571. 将整数减少到零需要的最少操作数 1649 巧妙结论
- 2568. 最小无法得到的或值 1754
- 2939. 最大异或乘积 2128
- 2749. 得到整数零需要执行的最少操作数 2132
- 2835. 使子序列的和等于目标的最少操作次数 2207
- 2897. 对数组执行操作使平方和最大 2301
- 810. 黑板异或游戏 2341
其它
- 136. 只出现一次的数字 (异或的性质)
- 287. 寻找重复数 (去除某个数, 然后统计1的个数复原它)
- 260. 只出现一次的数字 III
- 137. 只出现一次的数字 II (统计位数次数)
- 645. 错误的集合
- 190. 颠倒二进制位
- 371. 两整数之和
int getSum(int a, int b) {
int tmp = (a & b) << 1; // 记得要左移一位!
int res = a ^ b; // 相加(不理会进位的)
while (tmp) { // 是否要进位
int cache = tmp;
tmp = (res & tmp) << 1; // 进位
res = res ^ cache; // 相加(不理会进位的)
}
return res;
}
- 201. 数字范围按位与
- 2154. 将找到的值乘以 2 可以做到 时间
- 2044. 统计按位或能得到最大值的子集数目 1568 (子集型回溯)
- 2438. 二的幂数组中查询范围内的乘积 1610
- 1680. 连接连续二进制数字 1630
- 982. 按位与为零的三元组 2085
- 1611. 使整数变为 0 的最少操作次数 2345