题目## 题目
解题思路
计算一个整数的二进制表示中1的个数有几种常用方法:
-
位运算法:
- 使用 n & 1 n \& 1 n&1 判断最低位是否为1
- 右移运算 n > > = 1 n >>= 1 n>>=1 检查下一位
- 循环直到 n n n 变为0
-
Brian Kernighan算法:
- 利用 n & ( n − 1 ) n \& (n-1) n&(n−1) 可以消除最右边的1
- 每次操作都会消除一个1,直到 n n n 变为0
- 操作次数即为1的个数
代码
#include <iostream>
using namespace std;
int countOnes(int n) {
int count = 0;
while (n) {
n = n & (n - 1); // 消除最右边的1
count++;
}
return count;
}
int main() {
int n;
while (cin >> n) {
cout << countOnes(n) << endl;
}
return 0;
}
import java.util.Scanner;
public class Main {
public static int countOnes(int n) {
int count = 0;
while (n != 0) {
n &= (n - 1); // 消除最右边的1
count++;
}
return count;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
int n = sc.nextInt();
System.out.println(countOnes(n));
}
}
}
def countOnes(n):
count = 0
while n:
n &= (n - 1) # 消除最右边的1
count += 1
return count
while True:
try:
n = int(input())
print(countOnes(n))
except:
break
算法及复杂度
- 算法:Brian Kernighan算法
- 时间复杂度: O ( k ) \mathcal{O}(k) O(k),其中k是二进制中1的个数
- 空间复杂度: O ( 1 ) \mathcal{O}(1) O(1)
这个解法使用了Brian Kernighan算法,比普通的位运算方法更高效,因为它只需要循环1的个数次,而不是整数的位数次。对于输入数据范围 1 ≤ n ≤ 2 31 − 1 1 ≤ n ≤ 2^{31} - 1 1≤n≤231−1,这个方法都能高效处理。
解题思路
-
题目要求:
- 输入一个大于2的偶数
- 找出差值最小的两个素数,使它们的和等于输入的偶数
- 输出这两个素数(按从小到大顺序)
-
实现思路:
- 判断一个数是否为素数
- 从中间值向两边扩散查找
- 找到第一对符合条件的素数即为所求
-
具体步骤:
- 从 n / 2 n/2 n/2 开始,分别向左右查找
- 判断找到的数对是否都是素数
- 如果都是素数且和为 n n n,则找到答案
代码
#include <iostream>
using namespace std;
bool isPrime(int n) {
if (n < 2) return false;
for (int i = 2; i * i <= n; i++) {
if (n % i == 0) return false;
}
return true;
}
int main() {
int n;
while (cin >> n) {
// 从中间向两边查找
int mid = n / 2;
for (int i = 0; i <= mid; i++) {
if (isPrime(mid - i) && isPrime(mid + i)) {
cout << mid - i << endl << mid + i << endl;
break;
}
}
}
return 0;
}
import java.util.Scanner;
public class Main {
private static boolean isPrime(int n) {
if (n < 2) return false;
for (int i = 2; i * i <= n; i++) {
if (n % i == 0) return false;
}
return true;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
int n = sc.nextInt();
// 从中间向两边查找
int mid = n / 2;
for (int i = 0; i <= mid; i++) {
if (isPrime(mid - i) && isPrime(mid + i)) {
System.out.println(mid - i);
System.out.println(mid + i);
break;
}
}
}
}
}
def is_prime(n):
if n < 2:
return False
i = 2
while i * i <= n:
if n % i == 0:
return False
i += 1
return True
while True:
try:
n = int(input())
# 从中间向两边查找
mid = n // 2
for i in range(mid + 1):
if is_prime(mid - i) and is_prime(mid + i):
print(mid - i)
print(mid + i)
break
except EOFError:
break
算法及复杂度
- 算法:中心扩散法
- 时间复杂度: O ( n n ) \mathcal{O}(n\sqrt{n}) O(nn) - 每次判断素数需要 O ( n ) \mathcal{O}(\sqrt{n}) O(n),最多需要检查 O ( n ) \mathcal{O}(n) O(n)对数
- 空间复杂度: O ( 1 ) \mathcal{O}(1) O(1) - 只使用常数额外空间

392

被折叠的 条评论
为什么被折叠?



