牛客题解 | 奇数位丢弃
题目
解题思路
这是一道数学规律题,主要思路如下:
-
问题分析:
- 对 \(0 \dots n\) 的序列,每次丢弃奇数位置的数
- 需要找到最后剩下的数字
- 例如:对于 \(n=500\),最后剩下 \(255\)
-
解决方案:
- 观察规律可以发现,最后剩下的数是小于等于 \(n\) 的最大2的幂次数减1
- 通过位运算可以快速求解:
- 找到大于 \(n\) 的最小2的幂
- 将该数除以2再减1即为答案
-
数学证明:
- 每次删除奇数位后,剩余数字形成新序列
- 新序列的规律符合2的幂次数减1的形式
代码
#include <iostream>
using namespace std;
int findLastNumber(int n) {
// 找到大于n的最小2的幂
int power = 1;
while (power <= n + 1) {
power <<= 1;
}
// 返回该2的幂除以2再减1
return (power >> 1) - 1;
}
int main() {
int n;
while (cin >> n) {
cout << findLastNumber(n) << endl;
}
return 0;
}
import java.util.Scanner;
public class Main {
public static int findLastNumber(int n) {
// 找到大于n的最小2的幂
int power = 1;
while (power <= n + 1) {
power <<= 1;
}
// 返回该2的幂除以2再减1
return (power >> 1) - 1;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
int n = sc.nextInt();
System.out.println(findLastNumber(n));
}
}
}
def find_last_number(n: int) -> int:
# 找到大于n的最小2的幂
power = 1
while power <= n + 1:
power <<= 1
# 返回该2的幂除以2再减1
return (power >> 1) - 1
# 处理输入
while True:
try:
n = int(input())
print(find_last_number(n))
except EOFError:
break
算法及复杂度
- 算法:位运算
- 时间复杂度:\(\mathcal{O}(\log n)\) - 需要循环 \(\log n\) 次找到合适的2的幂
- 空间复杂度:\(\mathcal{O}(1)\) - 只需要常数额外空间

浙公网安备 33010602011771号