当前位置: 首页 > news >正文

移动应用开发实验室2024二面纳新题复盘

移动应用开发实验室2024二面纳新题复盘

@jarringslee

文章目录

  • 移动应用开发实验室2024二面纳新题复盘
    • [I. 洛谷B2110 找第一个只出现一次的字符 ](https://www.luogu.com.cn/problem/B2110)
    • 题目描述
    • 输入格式
    • 输出格式
    • 输入输出样例 #1
      • 输入 #1
      • 输出 #1
    • 输入输出样例 #2
      • 输入 #2
      • 输出 #2
    • [II. 洛谷B2136 素数回文数的个数 ](https://www.luogu.com.cn/problem/B2136)
    • 题目描述
    • 输入格式
    • 输出格式
    • 输入输出样例 #1
      • 输入 #1
      • 输出 #1
    • 说明/提示
    • [III. 洛谷B2111 基因相关性 ](https://www.luogu.com.cn/problem/B2111)
    • 题目描述
    • 输入格式
    • 输出格式
    • 输入输出样例 #1
      • 输入 #1
      • 输出 #1
    • [IV. 洛谷P1152 欢乐的跳](https://www.luogu.com.cn/problem/P1152)
    • 题目描述
    • 输入格式
    • 输出格式
    • 输入输出样例 #1
      • 输入 #1
      • 输出 #1
    • 输入输出样例 #2
      • 输入 #2
      • 输出 #2
    • 说明/提示
    • [V. 洛谷B2092 开关灯](https://www.luogu.com.cn/problem/B2092)
    • 题目描述
    • 输入格式
    • 输出格式
    • 输入输出样例 #1
      • 输入 #1
      • 输出 #1
    • 输入输出样例 #2
      • 输入 #2
      • 输出 #2
    • [VI. 洛谷B2140 二进制分类 ](https://www.luogu.com.cn/problem/B2140)
    • 题目描述
    • 输入格式
    • 输出格式
    • 输入输出样例 #1
      • 输入 #1
      • 输出 #1
    • [VII. 洛谷B3639 T2 点亮灯笼](https://www.luogu.com.cn/problem/B3639)
    • 题目背景
    • 题目描述
    • 输入格式
    • 输出格式
    • 输入输出样例 #1
      • 输入 #1
      • 输出 #1
    • 说明/提示
        • 样例解释
        • 数据规模与约定
    • [VIII. 洛谷P2249 查找 ](https://www.luogu.com.cn/problem/P2249)
    • 题目描述
    • 输入格式
    • 输出格式
    • 输入输出样例 #1
      • 输入 #1
      • 输出 #1
    • 说明/提示
    • [IX. 洛谷P1223 排队接水](https://www.luogu.com.cn/problem/P1223)
    • 题目描述
    • 输入格式
    • 输出格式
    • 输入输出样例 #1
      • 输入 #1
      • 输出 #1
    • 说明/提示

​ 在实验室经历了五个多月的学习和沉淀,我又迎来了一次考验自己的机会。经过两个半小时的酣战,我也深刻体会到了自己的渺小和与各路学长学姐们的差距。本次二面考核题目考察了数据结构的基础知识,以字符串处理和数学函数的基础应用为主,涵盖了dp、贪心、二分等算法知识。接下来,让我们一一解读其中的奥秘。

I. 洛谷B2110 找第一个只出现一次的字符

题目描述

给定一个只包含小写字母的字符串,请你找到第一个仅出现一次的字符。如果没有,输出 no

输入格式

一个字符串,长度小于 1100

输出格式

输出第一个仅出现一次的字符,若没有则输出 no

输入输出样例 #1

输入 #1

abcabd

输出 #1

c

输入输出样例 #2

输入 #2

aabbcc

输出 #2

no

​ 我们使用大小为26的整形数组来存储字符串中每个字母出现的次数,在通过遍历字符串找到第一个只出现过一次的字母并输出。很送分的一道题,我应该先把这题写了再看后面的题的。要是多给我两分钟我就又能AC一道了。唉

​ 上答案:

#include <stdio.h>

int main() {
    char str[1100];
    int count[26] = {0}; // 用于统计每个字符出现的次数

    // 读取输入字符串
    scanf("%s", str);

    // 统计每个字符出现的次数
    for (int i = 0; str[i] != '\0'; i++) {
        count[str[i] - 'a']++;
    }

    // 查找第一个只出现一次的字符
    for (int i = 0; str[i] != '\0'; i++) {
        if (count[str[i] - 'a'] == 1) {
            printf("%c\n", str[i]);
        }
    }
    return 0;
}

II. 洛谷B2136 素数回文数的个数

题目描述

11n 之间(包括 n),既是素数又是回文数的整数有多少个。

输入格式

一个大于 11 小于 10000 的整数 n

输出格式

11n 之间的素数回文数个数。

输入输出样例 #1

输入 #1

23

输出 #1

1

说明/提示

回文数指左右对称的数,如:1112121

​ 这道题依然简单粗暴。直接问你会不会写判断质数函数和判断回文数函数。

​ 我们可以通过循环取余个位数并除以十来判断回文数:

int isHuiwen(int n){
    int old = n;
    int now = 0;
    while(n > 0){
        now = now * 10 + n % 10;
        n /= 10;    
    }
    return old == now;   
}

​ 通过先处理掉小于等于3的数和2、3的倍数再用6k±1取余的方法来判断质数:

int isPrime(int b){
	if(n <= 1) return 0if(n <= 3) return 1;
	if(n % 2 == 0 || n % 3 == 0) return 0;
	for(int i = 5; i * i <= n; i += 6){
		if(n % i == 0 || n % (i + 2) == 0) return 0;
	}
	return 1;
}

​ 但是由于要判断i*i的情况,这会导致时间复杂度为O(n^2)。所以如果要用这个方法,我们在主函数中可以先判断回文数在判断质数,提高运行效率。这时候有人就要问了,主播我承认你判断质数的方法确实很强,但还是太吃复杂度了,有没有同样很强但是效率更高的方法?有的兄弟,有的。这么强的方法还有一个欧拉筛。这个方法需要把要判断的数组存到布尔数组中并利用已经找到的质数来标记合数,并且每个合数只被它的最小质因数标记一次。这样可以确保每个合数只被处理一次,从而提高效率。

void eulerSieve(int n, bool is_prime[]) {
    // 初始化所有数为质数
    memset(is_prime, true, sizeof(bool) * (n + 1));
    is_prime[0] = is_prime[1] = false; // 0和1不是质数

    for (int i = 2; i <= n; i++) {
        if (is_prime[i]) { // 如果i是质数
            // 将i的所有倍数标记为合数
            for (int j = i * 2; j <= n; j += i) {
                is_prime[j] = false;
            }
        }
    }
}

​ 上答案:

#include <stdio.h>
#include <stdbool.h>
#include <string.h>

void eulerSieve(int n, bool isPrime[]) {
    // 初始化所有数为质数
    memset(isPrime, true, sizeof(bool) * (n + 1));
    isPrime[0] = isPrime[1] = false; // 0和1不是质数

    for (int i = 2; i <= n; i++) {
        if (isPrime[i]) { 
            for (int j = i * 2; j <= n; j += i) {
                isPrime[j] = false;
            }
        }
    }
}

bool isHuiwen(int num) {
    if (num < 0) return false;
    int old = num;
    int now = 0;
    while (num > 0) {
        now = now * 10 + num % 10;
        num /= 10;
    }
    return old == now;
}

int main() {
    int N;
    scanf("%d", &N);

    // 创建布尔数组并调用欧拉筛法
    bool iPrime[N + 1];
    eulerSieve(N, is_prime);

    int cnt = 0;
    for (int i = 0; i <= N; i++) {
        if (isPrime[i] && isHeiwen(i)) {
            cnt++;
        }
    }

    printf("%d\n", cnt);
	return 0;
}

III. 洛谷B2111 基因相关性

题目描述

为了获知基因序列在功能和结构上的相似性,经常需要将几条不同序列的 DNA 进行比对,以判断该比对的 DNA 是否具有相关性。

现比对两条长度相同的 DNA 序列。首先定义两条 DNA 序列相同位置的碱基为一个碱基对,如果一个碱基对中的两个碱基相同的话,则称为相同碱基对。接着计算相同碱基对占总碱基对数量的比例,如果该比例大于等于给定阈值时则判定该两条 DNA 序列是相关的,否则不相关。

输入格式

有三行,第一行是用来判定出两条 DNA 序列是否相关的阈值,随后 2 行是两条 DNA 序列(长度不大于 500)。

输出格式

若两条 DNA 序列相关,则输出 yes,否则输出no

输入输出样例 #1

输入 #1

0.85
ATCGCCGTAAGTAACGGTTTTAAATAGGCC
ATCGCCGGAAGTAACGGTCTTAAATAGGCC

输出 #1

yes

​ 依旧是一道很友好的题。我们首先读取阈值n和两条DNA序列,然后遍历两条DNA序列的每个位置并统计相同碱基对的数量,最后计算相同碱基对占总碱基对数量的比例。到现在为止三道题有两道都是考且只考了字符串的简单应用。敢不敢考反转链表(bushi)

​ 上答案:

#include <stdio.h>
#include <string.h>

int main() {
    double n;
    char dna1[501], dna2[501];
    
    scanf("%lf", &n);
    scanf("%s", dna1);
    scanf("%s", dna2);
    
    int cnt = 0;
    int length = strlen(dna1);
    
    for (int i = 0; i < length; i++) {
        if (dna1[i] == dna2[i]) {
            cnt++;
        }
    }
    
    double sum = (double)cnt / length;
    printf(sum >= n ? "yes\n" : "no\n");
    
    return 0;
}

IV. 洛谷P1152 欢乐的跳

题目描述

一个 n个元素的整数数组,如果数组两个连续元素之间差的绝对值包括了[1,n-1] 之间的所有整数,则称之符合“欢乐的跳”,如数组\{1,4,2,3\}符合“欢乐的跳”,因为差的绝对值分别为:3,2,1

给定一个数组,你的任务是判断该数组是否符合“欢乐的跳”。

输入格式

每组测试数据第一行以一个整数 n(1 \le n \le 1000) 开始,接下来n 个空格隔开的在 [-10^8,10^8] 之间的整数。

输出格式

对于每组测试数据,输出一行若该数组符合“欢乐的跳”则输出 Jolly,否则输出 Not jolly

输入输出样例 #1

输入 #1

4 1 4 2 3

输出 #1

Jolly

输入输出样例 #2

输入 #2

5 1 4 2 -1 6

输出 #2

Not jolly

说明/提示

1 <= n <= 1000

​ 这道题在简单数组的基础上考了个排序。好像对时间复杂度的要求也不高。题目要求我们检查由给定的大小为n数组的相邻各个元素之间的差值组成的新数组,如果刚好是1到n-1那么就符合条件。我们先遍历数组,把ii+1的的差值储存到新的数组中并排序。这里用冒泡插入归并似乎可以。但是由于我比较厉害,我使用尊贵的快速排序,耗时短效率高:

// 比较函数
int compare(const void *a, const void *b) {
    return (*(int *)a - *(int *)b);
}

int main() {
    int n;
    scanf("%d", &n);
    int num[n];
    for (int i = 0; i < n; i++) {
        scanf("%d", &num[i]);
    }

    // 使用 qsort 函数排序
    qsort(num, n, sizeof(int), compare);
}

然后把排序好的数组分别和自身下标+1进行对比,全对得上那就符合条件。

上答案:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int compare(const void *a, const void *b) {
    return (*(int*)a - *(int*)b);
}

int main() {
    int n;
    while (scanf("%d", &n) != EOF) {
        if (n == 1) {//先排除只有一个元素的情况
            int x;
            scanf("%d", &x);
            printf("Jolly\n");
        } else {
            int a[n];
            for (int i = 0; i < n; i++) {
                scanf("%d", &a[i]);
            }
            int diffs[n-1];
            for (int i = 0; i < n-1; i++) {
                diffs[i] = abs(a[i+1] - a[i]);
            }//将相邻各个元素差值存入新数组
            qsort(diffs, n-1, sizeof(int), compare);//快排
            int isJolly = 1;
            for (int i = 0; i < n-1; i++) {
                if (diffs[i] != i + 1) {
                    isJolly = 0;
                    break;
                }
            }//这里我使用尊贵的三元运算符来输出结果。
            printf(isJolly ? "Jolly\n" : "Not jolly\n");
        }
    }
    return 0;
}

V. 洛谷B2092 开关灯

题目描述

假设有 N N N 盏灯( N N N 为不大于 5000 5000 5000 的正整数),从 1 1 1 N N N 按顺序依次编号,初始时全部处于开启状态;第一个人( 1 1 1 号)将灯全部关闭,第二个人( 2 2 2 号)将编号为 2 2 2 的倍数的灯打开,第三个人( 3 3 3 号)将编号为 3 3 3 的倍数的灯做相反处理(即,将打开的灯关闭,将关闭的灯打开)。依照编号递增顺序,以后的人都和 3 3 3 号一样,将凡是自己编号倍数的灯做相反处理。问当第 N N N 个人操作完之后,有哪些灯是关闭着的?

输入格式

输入为一行,一个整数 N N N,为灯的数量。

输出格式

输出为一行,按顺序输出关着的灯的编号。编号与编号之间间隔一个空格。

输入输出样例 #1

输入 #1

10

输出 #1

1 4 9

输入输出样例 #2

输入 #2

5

输出 #2

1 4

​ 这道题乍一看确实很唬人。感觉会有点无从下手,不知道在靠什么。但是其实也就是题目有点难以理解。其实,如果一个灯最终是否关闭的只取决于它的编号是否一个平方数。这是因为每个灯被操作的次数等于它的因数的个数,而只有平方数的因数个数是奇数。每盏灯初始时是开启的。每个人会根据自己的编号对灯进行操作。如果编号是该人的倍数,则将灯的状态反转(开变关,关变开)。最终,灯的状态取决于被操作的次数是否为奇数次。

​ 而一个数的因数个数如果是奇数,则该数是一个平方数。因为平方数的因数是成对出现的,除了平方根本身。我们可以遍历所有可能的平方数,检查它们是否小于等于N。如果是,则这些灯最终是关闭的。

​ 所以经过对题目的层层抽丝剥茧,我们发现题目只需要让我们输出给定范围中的所有平方数。这道题的难点就在于理解通过编号来翻转灯的状态的规律。其实我们如果简单的尝试几组,便能很快寻得规律。

上答案:

#include <stdio.h>
#include <math.h>

int main() {
    int N;
    scanf("%d", &N);
    
    int maxSqrt = (int)sqrt(N);
    int result[maxSqrt];
    int cnt = 0;
    
    for (int i = 1; i <= maxSqrt; i++) {
        int square = i * i;
        if (square <= N) {
            result[cnt++] = square;
        } else {
            break;
        }
    }
    
    for (int i = 0; i < cnt; i++) {
        if (i > 0) {
            printf(" ");
        }
        printf("%d", result[i]);
    }
    printf("\n");
    
    return 0;
}

VI. 洛谷B2140 二进制分类

题目描述

若将一个正整数化为二进制数,在此二进制数中,我们将数字 1 1 1 的个数多于数字 0 0 0 的个数的这类二进制数称为 A A A 类数,否则就称其为 B B B 类数。

例如:

( 13 ) 10 = ( 1101 ) 2 (13)_{10}=(1101)_2 (13)10=(1101)2,其中 1 1 1 的个数为 3 3 3 0 0 0 的个数为 1 1 1,则称此数为 A A A 类数;

( 10 ) 10 = ( 1010 ) 2 (10)_{10}=(1010)_2 (10)10=(1010)2,其中 1 1 1 的个数为 2 2 2 0 0 0 的个数也为 2 2 2,称此数为 B B B 类数;

( 24 ) 10 = ( 11000 ) 2 (24)_{10}=(11000)_2 (24)10=(11000)2,其中 1 1 1 的个数为 2 2 2 0 0 0 的个数为 3 3 3,则称此数为 B B B 类数;

程序要求:求出 1~n 之中( 1 ≤ n ≤ 1000 1 \le n \le 1000 1n1000),全部 A , B A,B A,B 两类数的个数。

输入格式

输入 n n n

输出格式

一行,包含两个整数,分别是 A A A 类数和 B B B 类数的个数,中间用单个空格隔开。

输入输出样例 #1

输入 #1

7

输出 #1

5 2

​ 一看到二进制我就头疼。但好在这道题对二进制知识的要求不是很高,只涉及一个十进制和二进制的相互转换。

​ 这个问题要求我们统计1到n之间A类数和B类数的数量。A类数是指二进制表示中1的个数多于0的个数的数,而B类数则相反。对于每个数,我们需要将其转换为二进制,并统计其中1和0的个数。然后遍历1到n之间的每个数,计算其二进制表示中1和0的个数,并根据条件分类计数。

​ 为了高效计算二进制中1的个数,我们可以使用尊贵的位运算。

​ 上答案:

#include <stdio.h>
#include <math.h>

int countOnes(int num) {
    int count = 0;
    while (num > 0) {
        count += num & 1;
        num >>= 1;
    }
    return count;
}

int main() {
    int n;
    scanf("%d", &n);
    
    int aCount = 0, bCount = 0;
    
    for (int i = 1; i <= n; i++) {
        int ones = countOnes(i);
        int bits = (int)log2(i) + 1; // 计算二进制位数
        int zeros = bits - ones;
        
        if (ones > zeros) {
            aCount++;
        } else {
            bCount++;
        }
    }
    
    printf("%d %d\n", aCount, bCount);
    
    return 0;
}

VII. 洛谷B3639 T2 点亮灯笼

题目背景

请尽量在 20min 之内写完题目。这是指「写代码」的时间;「读题」时间不计算在内。

题目描述

n n n 个灯笼环形摆放。最开始,这些灯笼都是关闭的状态。

操作台上有 n n n 个按钮,按下第 x x x 个按钮时,会反转灯笼 x x x 以及相邻两个灯笼的状态。「反转」是指关闭变成点亮、点亮变成关闭。

举一个例子:如果按下第 5 5 5 个按钮,则 4 4 4 5 5 5 6 6 6 号灯笼都会反转;如果按下第 n n n 个按钮,则 n − 1 , n , 1 n-1, n, 1 n1,n,1 这三个灯笼状态反转。这是因为灯笼放置为环形, n − 1 n-1 n1 1 1 1 是与 n n n 相邻的灯笼。

我们依次按下了一些按钮。你需要编程求出当我们的操作完成后,最终这些灯笼的状态。

输入格式

第一行,两个正整数 n , m n, m n,m,分别表示共有 n n n 个灯笼、我们按了 m m m 次按钮。

接下来 m m m 行,每行一个正整数,表示我们在那一次操作中按下了哪个按钮。

输出格式

仅一行, n n n 个整数,依次表示 n n n 个灯笼的状态,用空格隔开。以 0 代表灯笼关闭,以 1 代表灯笼点亮。

输入输出样例 #1

输入 #1

5 4
1
3
1
2

输出 #1

1 0 0 1 0

说明/提示

样例解释

灯笼序列的状态如下:

0 0 0 0 0  # 初始状态
1 1 0 0 1  # 按下 1 之后的状态
1 0 1 1 1  # 按下 3 之后的状态
0 1 1 1 0  # 按下 1 之后的状态
1 0 0 1 0  # 按下 2 之后的状态

因此你应当输出 1 0 0 1 0

数据规模与约定

对于 100 % 100\% 100% 的数据,有 n ≤ 1000 n\leq 1000 n1000 m ≤ 1000 m\leq 1000 m1000

​ 我要晕字了。

​ 我们有n个灯笼环形摆放,初始状态都是关闭的(0)。每次按下某个按钮时,会反转该按钮对应的灯笼及其相邻两个灯笼的状态。我们需要模拟这个过程,最终输出所有灯笼的状态。该怎么去实现呢。。。我们一步一步来想。

  • 使用一个数组 status 来表示灯笼的状态,初始时所有灯笼都是关闭的(0)。
  • 每次按下按钮时,反转该按钮对应的灯笼及其相邻两个灯笼的状态。
  • 灯笼是环形摆放的,因此需要处理边界情况(例如,第1个灯笼的前一个灯笼是第n个灯笼,第n个灯笼的下一个灯笼是第1个灯笼)。
  • 还要遍历每个按钮操作,更新灯笼的状态。

​ okok。那么我们就开一个数组然后利用索引来调节灯笼的状态。首先创建一个大小为n的数组 status,初始值为0(表示所有灯笼关闭)。接下来,我们处理每个按钮操作:

  1. 将输入的按钮编号转换为0-based索引。
  2. 反转当前按钮对应的灯笼的状态。
  3. 反转前一个灯笼的状态(使用 (x - 1 + n) % n 处理环形边界)。
  4. 反转后一个灯笼的状态(使用 (x + 1) % n 处理环形边界)。

​ 最后遍历数组 status,输出每个灯笼的状态。

​ 上答案:

#include <stdio.h>

int main() {
    int n, m;
    scanf("%d %d", &n, &m);
    
    int status[n]; // 0表示关闭,1表示点亮
    for (int i = 0; i < n; i++) {
        status[i] = 0; // 初始状态全部关闭
    }
    
    for (int i = 0; i < m; i++) {
        int x;
        scanf("%d", &x);
        x--; // 将输入的1-based转换为0-based
        
        // 反转当前按钮对应的灯笼
        status[x] = !status[x];
        
        // 反转前一个灯笼(考虑环形)
        int prev = (x - 1 + n) % n;
        status[prev] = !status[prev];
        
        // 反转后一个灯笼(考虑环形)
        int next = (x + 1) % n;
        status[next] = !status[next];
    }
    
    for (int i = 0; i < n; i++) {
        if (i > 0) {
            printf(" ");
        }
        printf("%d", status[i]);
    }
    printf("\n");
    
    return 0;
}

VIII. 洛谷P2249 查找

题目描述

输入 n n n 个不超过 1 0 9 10^9 109 的单调不减的(就是后面的数字不小于前面的数字)非负整数 a 1 , a 2 , … , a n a_1,a_2,\dots,a_{n} a1,a2,,an,然后进行 m m m 次询问。对于每次询问,给出一个整数 q q q,要求输出这个数字在序列中第一次出现的编号,如果没有找到的话输出 − 1 -1 1

输入格式

第一行 2 2 2 个整数 n n n m m m,表示数字个数和询问次数。

第二行 n n n 个整数,表示这些待查询的数字。

第三行 m m m 个整数,表示询问这些数字的编号,从 1 1 1 开始编号。

输出格式

输出一行, m m m 个整数,以空格隔开,表示答案。

输入输出样例 #1

输入 #1

11 3
1 3 3 3 5 7 9 11 13 15 15
1 3 6

输出 #1

1 2 -1

说明/提示

数据保证, 1 ≤ n ≤ 1 0 6 1 \leq n \leq 10^6 1n106 0 ≤ a i , q ≤ 1 0 9 0 \leq a_i,q \leq 10^9 0ai,q109 1 ≤ m ≤ 1 0 5 1 \leq m \leq 10^5 1m105

本题输入输出量较大,请使用较快的 IO 方式。

​ 从这道题开始,题目不再从题眼上花费心思建立难懂的逻辑,而是降低读题难度,提高解题难度。而且这道题有复杂度要求,要不是这道题就躺在洛谷二分法题单的第一题我有幸与之交过手,我可能还真被难住了。

​ 题目明令禁止暴力解法,其实就是想考察你会不会二分法。你要是知道有这么个东西那这就是一道简单题,要是没看过二分法那你就完蛋了。

​ 我们首先需要知道二分查找是一个快速在有序数组中找到目标数的查找方法,复杂度为O(n)。我们首先取有序数组的首位元素和末位元素为左右索引,并且定义整数mid为左右索引间最中间的数(初始值就是整个数组的中间数)。如果mid等于目标数那就直接输出,如果mid大于目标数,那就把左索引更新为mid-1,mid也会随之更新;如果小于目标数,那就更新右索引。直到使mid等于目标数。

​ 当然,题目还有一个心眼,就是可能会有重复的数字,这意味着我们找到目标数还需要看看左边的数字是否重复:

int search(int arr[], int target, int len){
    int left = 0;
    int right = len - 1;
    int result = -1;
    while(left <= right){
        int mid = left + (right - left) / 2;
        if(arr[mid] == target){
            result = mid;
            right = mid - 1;
        }else if(arr[mid] > target){ 
            right = mid - 1;
        }else{
            left = mid + 1;
        }    
    }
    return result;
}

​ 二分法不难。但前提是你必须知道有这么个逻辑。

​ 最后,数组时无序的,那么我们需要拿出尊贵的快排来进行排序。

​ 上答案:

#include<stdio.h>
int search(int arr[], int target, int len){
    int left = 0;
    int right = len - 1;
    int result = -1;
    while(left <= right){
        int mid = left + (right - left) / 2;
        if(arr[mid] == target){
            result = mid;
            right = mid - 1;
        }else if(arr[mid] > target){ 
            right = mid - 1;
        }else{
            left = mid + 1;
        }    
    }
    return result;
}
int main(){
    int n,m;
    scanf("%d %d",&n,&m);
    int arr[n];
    for(int i = 0;i < n;i++){
        scanf("%d",&arr[i]);
    }
    int question[m];
    for(int i = 0;i < m;i++){
        scanf("%d",&question[i]);
    }
    int answer[m];
    for(int i = 0;i < m;i++){
        int index = search(arr,question[i],n);
        answer[i] = (index == -1) ? index : (index + 1);
    }

    for(int i;i < m;i++){
        printf("%d ",answer[i]);
    }
    return 0;
}

IX. 洛谷P1223 排队接水

题目描述

n n n 个人在一个水龙头前排队接水,假如每个人接水的时间为 T i T_i Ti,请编程找出这 n n n 个人排队的一种顺序,使得 n n n 个人的平均等待时间最小。

输入格式

第一行为一个整数 n n n

第二行 n n n 个整数,第 i i i 个整数 T i T_i Ti 表示第 i i i 个人的接水时间 T i T_i Ti

输出格式

输出文件有两行,第一行为一种平均时间最短的排队顺序;第二行为这种排列方案下的平均等待时间(输出结果精确到小数点后两位)。

输入输出样例 #1

输入 #1

10 
56 12 1 99 1000 234 33 55 99 812

输出 #1

3 2 7 8 1 4 9 6 10 5
291.90

说明/提示

1 ≤ n ≤ 1000 1\le n \leq 1000 1n1000 1 ≤ t i ≤ 1 0 6 1\le t_i \leq 10^6 1ti106,不保证 t i t_i ti 不重复。

​ 压轴题在考察函数排序数组等知识的基础上多考了个结构体。当然还是那句话,考到的知识层面都是比较浅的。只要认识了结构体,学习了结构体的定义和调用,问题都不大。

​ 我们在这里要输出两个东西,一个是编号,一个是时间。

​ 我们会发现将数组排序后输出的是元素而不是编号,这里我们就该用到结构体,包含成员时间和成员编号,将结构体根据时间排序后再输出编号。这里我们依旧选择尊贵的快速排序。

​ 至于时间,我们通过累加每个人开始接水前的总时间(now)来计算总等待时间。最后别忘了用浮点数计算平均时间。

​ 上答案:

#include<stdio.h>
#include<stdlib.h>

typedef struct{
    int time;
    int num;
}student;


int compare(const void*a,const void*b){
    student *p1 = (student *)a;
    student *p2 = (student *)b;
    return p1 -> time - p2 -> time;
}



int main() {
    int n;
    scanf("%d",&n);
    student arr[n];


    for(int i = 0;i < n;i++){
        scanf("%d",&arr[i].	time);
        arr[i].num = i + 1;
    }

    qsort(arr, n, sizeof(student), compare);

    long long now = 0;
    long long total = 0;

    for(int i = 0;i < n;i++) {
        printf("%d",arr[i].num);
        if( i < n - 1){
            printf(" ");
        }
        total +=  now;
        now += arr[i].time;  
    }
    printf("\n");

    double ave = (double)total / n;
    printf("%.2f",ave);
    return 0;
}

相关文章:

  • 【家政平台开发(20)】系统监控与日志管理设计:稳固运行的基石
  • 【内网安全】DHCP 饿死攻击和防护
  • [特殊字符] 驱动开发硬核特训 · Day 4
  • Vue3响应式引擎解密:从依赖追踪到性能调优的深度之旅
  • 微服务系统记录
  • Java 数组与 ArrayList 核心区别解析:从源码到实战!!!
  • 远距离无线网络传输设备-网桥(1/5/15 km)
  • C++Primer - 动态内存管理
  • 优选算法的妙思之流:分治——归并专题
  • 静态库与动态库
  • 整理一些大模型部署相关的知识
  • 对责任链模式的理解
  • 7.4 SVD 的几何背景
  • JCR一区文章,壮丽细尾鹩莺算法Superb Fairy-wren Optimization-附Matlab免费代码
  • 介质访问控制——信道划分
  • from fastmcp import FastMCP和from mcp.server.fastmcp import FastMCP的区别是什么?
  • C51单片机学习笔记——LCD1602调试
  • SEO长尾关键词优化策略
  • 语法: value=kbhit( );和 value=kbhit( stream );
  • 10天速通强化学习-009--DDPG、SAC、TD3
  • 用wordpress做的网站有哪些/头条收录提交入口
  • 旅游网站设计与建设论文/软文大全
  • 做哪类视频网站需要视频牌照/英文网站设计公司
  • 阿里云怎么做淘宝客网站/枣庄网站建设制作
  • 政府网站建设风险分析/太原今日新闻最新头条
  • 网站里的搜索怎么做/百度认证怎么认证