CSDN编程题-每日一练(2023-08-26)
- 一、题目名称:排查网络故障
- 二、题目名称:贪食四人帮
- 三、题目名称:阿波罗的魔力宝石
一、题目名称:排查网络故障
时间限制:1000ms内存限制:256M
题目描述:
A地跟B地的网络中间有n个节点(不包括A地和B地),相邻的两个节点是通过网线连接。正常的情况下,A地和B地是可以连通的,有一天,A地和B地突然不连通了,已知只有一段网线出问题(两个相邻的节点)小明需要排查哪段网线出问题。他的排查步骤是: 1。 选择某个中间节点 2。 在这个节点上判断跟A地B地是否连通,用来判断那一边出问题 请问小明最少要排查多少次,才能保证一定可以找到故障网线。
输入描述:
一个正整数 n (n <= 10^18),表示A地和B地之间的节点数。
输出描述:
输出一个数字,代表保证一定可以找到故障网线的前提下,小明最少要排查多少次?
🚩示例:
✔️示例1
输入
2
输出
2
🔔 解题思路:
假设节点数为n,我们可以将整个网络划分为两半,即左边的节点和右边的节点。如果某个节点被选为判断节点,那么它所在的位置就决定了是哪一半出了问题。
对于一个给定的节点数n,首先找到最接近n的2的幂次方m,使得m <= n。然后,排查的次数就是最接近n的2的幂次方的对数log2(m)。
首先观察题目中的连接方式,可以发现节点数n与排查次数node_number之间存在一定的关系。
1、假设排查次数为x,那么排查的节点个数应为2^x - 1。
2、当排查的节点个数超过了n时,即2^x - 1 > n,说明排查次数为x-1时已经可以确定故障网线的位置。
3、根据以上思路,可以用循环不断将n除以2,直到n小于等于0为止,每次循环时check_number 加1。
4、最后输出check_number 即为所求的最少排查次数。
代码1如下:
##A地和B地之间的节点数n
n = int(input())
##计数器check_number , 排查次数
check_number = 0
##当n大于0时,执行循环体
while n > 0:
##将n除以2,结果赋值给n,相当于将节点数减半,直到n小于等于0为止
n = n // 2
###每次循环时,将check_number 加1
check_number += 1
###输出check_number即为所求的最少排查次数
print(check_number)
代码2如下:
🔔 解题思路:
首先,我们需要找到一个节点,通过判断这个节点是否与A地和B地连通,来确定故障网线是在节点的哪一边。
假设A地和B地之间有n个节点,我们可以将节点数n表示成二进制形式。例如,n=2时,二进制为10,表示有两个节点。
我们观察一下,当节点数为2的幂次方时,排查次数最少。例如,n=2时,只有节点2需要排查;n=4时,只有节点4需要排查;n=8时,只有节点8需要排查,以此类推。
因此,我们可以先找到节点数n的二进制表示中最高位的1的位置,记为highest_bit_pos。然后,我们构造一个掩码mask,将最高位1右边的所有位都置为1。再将节点数n与掩码mask进行或运算,得到masked_n。
最后,我们统计masked_n中1的个数,即为小明最少要排查的次数。
n = int(input())
# 1、找到最高位1的位置,即二进制字符串的长度减去3,
### 如: bin(2)的结果是字符串'0b10'。长度为4,这表示二进制数2的二进制表示形式为10。前缀0b表示这是一个二进制数,最高位为1
highest_bit_pos = len(bin(n)) - 3
# 2、将最高位1右边的所有位都置为1
##使用左移运算符<<将1左移highest_bit_pos个位数,然后减去1,生成一个二进制数,其中最高位1的右边都是1,其余位为0。这个二进制数被赋值给变量mask
mask = (1 << highest_bit_pos) - 1
##3、按位或运算符|将n与mask进行按位或操作
###将masked_n的最高位1右边的所有位都置为1,而其余位与n保持相同
masked_n = n | mask
# 4、计算1的个数
##将masked_n转换为二进制字符串,然后使用count()函数计算其中字符'1'的个数
count = bin(masked_n).count('1')
#5、输出count,即masked_n中1的个数
print(count)
🔔 示例输入解释:
例如,当输入为2时,输出为2。解释:
1、节点数n为2,二进制表示为10。
2、找到最高位1的位置为1,即highest_bit_pos=1。
3、构造掩码mask,将最高位1右边的所有位都置为1,即mask=1。
4、将节点数n与掩码mask进行或运算,得到masked_n=3。
5、统计masked_n中1的个数,即为小明最少要排查的次数,即count=2。
二、题目名称:贪食四人帮
时间限制:1000ms内存限制:256M
题目描述:
已知等比数列前4项,首项为a,公比为q。 前四项分别是a,aq,aqq,aqqq。 现在一直只存在n个组合方案。 请问n种方案中,方案中包含的最大值是多少?
输入描述:
输入整数n.(1<=n<=1e15)
输出描述:
输出答案,不存在满足的情况输出”-1”。
🚩示例:
✔️示例1
输入
8
输出
54
代码如下:
n = int(input())
if n == 1:
max_value = 1
elif n >= 4:
max_value = 2 ** 3 if n == 4 else -1
else:
max_value = -1
print(max_value)
三、题目名称:阿波罗的魔力宝石
时间限制:1000ms内存限制:256M
题目描述:
在希腊神话中,有一个神祗阿波罗。阿波罗拥有一枚能够使人变得更加聪明的神奇宝石。但是,这枚宝石的魔力被封印在了一个混乱的顺序中,你需要通过排序的方法才能拥有这枚宝石的魔力。 给定一个长度为 N N N 的整数数组 A A A,请你将数组 A A A 中的元素进行冒泡排序。
输入描述:
第一行包含整数 N N N。 第二行包含 N N N 个整数,表示数组 A A A。
输出描述:
输出 N N N行,每行包含一个整数,表示排序后的数组 A A A。
🚩示例:
✔️示例1
输入
5
2 5 3 1 4
输出
1
2
3
4
5
🔔 解题思路:
使用冒泡排序:
冒泡排序是一种基本的排序算法。它重复地遍历要排序的数组,每次比较相邻的两个元素并交换位置,直到整个数组有序。
解题思路:
根据题目描述,需要使用冒泡排序算法对给定的整数数组A进行排序。冒泡排序的基本思想是通过相邻元素的比较和交换来实现排序。
冒泡排序的具体步骤如下:
1、从第一个元素开始,依次比较相邻的两个元素,如果前一个元素大于后一个元素,则交换它们的位置。
2、继续向后遍历,进行相邻元素的比较和交换,直到达到倒数第二个元素。
3、重复以上步骤,每次遍历都将最大的元素“冒泡”到未排序部分的最后位置。
4、重复上述步骤多次,直到整个数组有序为止。
使用双重循环实现冒泡排序:
1、外层循环控制遍历次数,共需遍历N-1次(N为数组长度)。
2、内层循环用于比较相邻元素并进行交换,每次遍历只需比较相邻的前后两个元素。
3、每完成一次内层循环,最大的元素就会“冒泡”到未排序部分的最后位置。
4、最终得到排序后的数组A,按照顺序逐行输出即可。
代码1如下:
N = int(input()) # 读取整数N,表示数组长度
# 读取整数数组A,使用split()方法将输入字符串分割成多个子字符串,并将每个子字符串转换为整数,再将它们组成一个列表。
A = list(map(int, input().split()))
# 冒泡排序,使用冒泡排序算法对数组A进行排序
## 通过双重循环进行冒泡排序:
## 1、外层循环 for i in range(N-1) 控制遍历次数,从0到N-2。
## 2、内层循环 for j in range(N-i-1) 用于比较相邻元素并进行交换。
## 3、如果当前元素 A[j] 大于下一个元素 A[j+1],则交换它们的位置,实现升序排序。
for i in range(N-1):
for j in range(N-i-1):
if A[j] > A[j+1]:
A[j], A[j+1] = A[j+1], A[j]
# 按照顺序逐行输出排序后的数组A
for num in A:
print(num)
代码2如下:
#include <stdio.h>
void sort(int arr[], int n) {
for (int i = 0; i < n-1; i++) {
for (int j = 0; j < n-i-1; j++) {
if (arr[j] > arr[j+1]) {
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
int main() {
int N;
scanf("%d", &N); // 读取整数N,表示数组长度
int A[N];
for (int i = 0; i < N; i++) {
scanf("%d", &A[i]); // 读取整数数组A
}
// 冒泡排序
sort(A, N);
// 输出排序后的数组A
for (int i = 0; i < N; i++) {
printf("%d\n", A[i]);
}
return 0;
}
代码3如下:
#include <iostream>
#include <vector>
void sort(std::vector<int>& arr) {
int n = arr.size();
for (int i = 0; i < n-1; i++) {
for (int j = 0; j < n-i-1; j++) {
if (arr[j] > arr[j+1]) {
std::swap(arr[j], arr[j+1]);
}
}
}
}
int main() {
int N;
std::cin >> N; // 读取整数N,表示数组长度
std::vector<int> A(N);
for (int i = 0; i < N; i++) {
std::cin >> A[i]; // 读取整数数组A
}
// 冒泡排序
sort(A);
// 输出排序后的数组A
for (int i = 0; i < N; i++) {
std::cout << A[i] << "\n";
}
return 0;
}