2024西游新生赛部分题解

文章目录

  • B 我才是奶龙
    • 题目大意
    • 题目分析
    • 答案
  • D 琪露诺和三角形
    • 题目大意
    • 题目分析
    • 方法一
    • 方法二
  • J 六花和薯片
    • 题目大意
    • 题目分析
  • K 小鸟游的寒假
    • 题目大意
    • 题目分析
  • L 白小藜和合数
    • 题目大意
    • 题目分析

B 我才是奶龙

题目大意

众所周知,奶龙是一只喜欢重量级的黄色 小龙,现在有一只小白龙试图变成奶龙,但是颜色和奶龙不一样(一个白色一个黄色);于是他找到R G B三种颜色,自己调出黄色给自己上色。

为了简化问题,我们用三个字符R、G、B分别表示红色、绿色和蓝色;如果小白龙可以调出黄色输出YES,否则输出NO。输出不包括引号,注意大小写。

注:黄色只能由红色和绿色相加而成,换句话说,挑选的颜色中恰好只有R和G时输出YES;否则输出NO

输入格式

第一行输入一个整数n表示小白龙选择的颜色数量(1 <= n <= 3)。

接下来依次输入n行,每行输出R、G、B 中的其中一个代表小白龙选择的颜色。小白龙可以选择同一个颜色不止一次,详情看第三组样例。

输出格式

小白龙可以调出黄色输出YES,否者输出NO。

样例数据

输入1

复制代码
3
R
G
B

输出1

复制代码
NO

输入2

复制代码
2
G
R

输出2

复制代码
YES

输入3

复制代码
3
R
G
R

输出3

复制代码
YES

样例解释

样例一:输入不仅包含R、G还有B,不符合恰好只有R、G,故输出NO。

样例二:输入只包含R、G,故输出YES。

样例三:输入虽然有三个颜色,R选了两次,但是恰好只有R、G,故输出YES。

题目分析

​ 我们需要判断小白龙挑选的颜色是否构成恰好合成绿色的条件,换句话说就是判断输入的所有字母中是否只包含R和G而不包含B。这道题我们理论上可以使用布尔数组来分别存储并判断是否出现R、G、B的情况,但由于我是若至,我希望拿我仅学到数组的脑子来解开这道题。那么,我们该怎么做呢?

​ 首先,关闭电脑,洗洗睡吧。

​ 其次,我们根据题目要求的输入格式输入一个整数n和一个大小为n的字符型数组。但是如果直接arr[n]的话翻车的可能性极大,所以我们使用动态内存分配:

c 复制代码
    int n;
    scanf("%d", &n);
    char *arr = (char *)malloc((n) * sizeof(char));
    if (arr == NULL) {
        return 1;
    }

​ 注意,如果要输入字符型数组元素,当你使用scanf("%c", &arr[i]);时,如果输入流中存在空白字符(如换行符),它们会被读取并存储在数组中。这可能会导致你的逻辑出错。你可以使用scanf(" %c", &arr[i]);(注意%c前的空格)来忽略任何空白字符:

c 复制代码
for (int i = 0; i < n; i++) {
        scanf(" %c", &arr[i]); 
    }
    arr[n] = '\0'; 

​ 遍历完数组,我们需要判断这个数组的成分。比较简单的一个方法就是,我们定义三个整数并初始化为0,然后我们在遍历整个数组,如果遍历到某一个字母,就给相应的数字赋值1(因为在一遍遍的循环中,只要某个字母对应的整数有一次被赋值为1,那么不管这个字母后面是否出现或出现几次,它所对应的整数都一定保持为1)。

​ 遍历完数组后,我们仅需一个if语句即可判断输入是否所需题目要求。

c 复制代码
    int r = 0, g = 0, b = 0;

    for (int j = 0; j < n; j++) {
        if (arr[j] == 'R') {
            r = 1;
        } else if (arr[j] == 'G') {
            g = 1;
        } else if (arr[j] == 'B') {
            b = 1;
        }
    }

    if (r == 1 && g == 1 && b == 0) {
        printf("YES\n");
    } else {
        printf("NO\n");
    }

答案

c 复制代码
#include <stdio.h>
#include <stdlib.h>

int main() {
    int n;
    scanf("%d", &n);
    // 使用动态内存分配来创建数组
    char *arr = (char *)malloc((n) * sizeof(char));
    if (arr == NULL) {
        // 如果内存分配失败,退出程序
        return 1;
    }

    for (int i = 0; i < n; i++) {
        scanf(" %c", &arr[i]); // 注意%c前的空格,用于忽略空白字符
    }
    arr[n] = '\0'; // 确保字符串以空字符结尾

    int r = 0, g = 0, b = 0;

    for (int j = 0; j < n; j++) {
        if (arr[j] == 'R') {
            r = 1;
        } else if (arr[j] == 'G') {
            g = 1;
        } else if (arr[j] == 'B') {
            b = 1;
        }
    }

    // 检查是否同时出现'R'和'G',并且没有出现'B'
    if (r == 1 && g == 1 && b == 0) {
        printf("YES\n");
    } else {
        printf("NO\n");
    }

    // 释放动态分配的内存
    free(arr);
    return 0;
}

D 琪露诺和三角形

题目大意

给你一个实数 T T T,构造一个周长面积都为 T T T 的三角形。

题目分析

这道题要求构造一个周长和面积都为给定实数 T 的三角形。提供了两种方法来解决该问题,方法一利用椭圆焦点三角形的性质来确定是否有解以及构造三角形;方法二则假设构造等腰三角形,通过二分法求解边长。

方法一

c 复制代码
#include <stdio.h>
#include <math.h>

void calculate(double T)
{
    double a,b,c,y;
    c=T/6;
    a=T/2-c;
    b=sqrt((T*T/4)-T*c);
    y =T/(2*c);

    // 输出三角形顶点坐标,焦点在x轴上,两个焦点坐标为(-c, 0)和(c, 0),第三个顶点坐标为(0, y)
    printf("(%.10lf, 0.0000000000)\n", -c);
    printf("(%.10lf, 0.0000000000)\n", c);
    printf("(0.0000000000, %.10lf)\n", y);
}

int main() {
    double T;
    scanf("%lf", &T);

    if (T>= 12*sqrt(3)) 
    {
        calculate(T);
    } else 
    {
        printf("No\n");
    }

    return 0;
}

首先根据椭圆焦点三角形周长恒定的性质,已知周长 T,计算出半焦距 c = T / 6。然后计算半长轴 a = T / 2 - c。接着通过椭圆的性质 a^2 = b^2 + c^2,计算半短轴 b = sqrt((T * T / 4) - T * c)。最后计算焦点三角形的高 y = T / (2 * c),这里假设焦点在 x 轴上,两个焦点坐标为 (-c, 0)(c, 0),第三个顶点坐标为 (0, y)

从控制台读取输入的实数 T。判断 T 是否大于等于 12 * sqrt(3),如果是,则调用 calculateTriangle 函数计算并输出三角形的顶点坐标;否则输出 No 表示无解。

方法二

c 复制代码
#include <stdio.h>
#include <math.h>

//计算等腰三角形的边长
double calculate(double T,double low,double high) {
    double mid,a,b,S,C;
    while (high-low>1e-10)
     {
        mid = (low+high)/2;
        // 底
        a = 2*sqrt(mid * mid - (T / 4) * (T / 4));
        // 腰
        b = (T - a / 2);
        // 面积
        S = 0.5*a*sqrt(b*b - (a / 2)*(a / 2));
        // 周长
        C = 2*a + b;

        // 根据面积和周长与目标值的比较调整二分区间
        if (S > T || C < T) {
            high = mid;
        } else if (S < T || C > T) {
            low = mid;
        } else {
            return b;
        }
    }
    return -1;
}

int main() {
    double T, b;
    scanf("%lf", &T);

    // 初始化二分查找区间
    
    double low = T / 4, high = T / 2;
    side = calculate(T,low,high);

    if (side!= -1) {
        // 输出等腰三角形的边长
        printf("%.10lf\n", b);
        printf("%.10lf\n", b);
        printf("%.10lf\n", 2 * sqrt(side * side - (T / 4) * (T / 4)));
    } else {
        printf("No\n");
    }

    return 0;
}

计算等腰三角形边长的函数 calculate,函数使用二分法来逼近满足条件的等腰三角形边长。

首先在 while 循环中,不断计算二分区间的中间值 mid。然后计算底边长度 a = 2 * sqrt(mid * mid - (T / 4) * (T / 4)),这里利用了等腰三角形的性质(假设腰长为 mid,根据勾股定理计算底边)。接着计算腰长 b = (T - base) / 2。再计算面积 S = 0.5 * a * sqrt(b * b - (a/ 2) * (a / 2)) 和周长 C = 2 * b + a。根据面积和周长与目标值 T 的比较结果来调整二分区间,如果 S> T 或者 C < T,说明当前边长过大,将 high 更新为 mid;如果 S < T 或者 C > T,说明当前边长过小,将 low 更新为 mid;如果面积和周长都等于 T,则返回当前边长 b

J 六花和薯片

题目大意

三个人分别每 t 1 、 t 2 、 t 3 t_1、t_2、t_3 t1、t2、t3 秒吃一个薯片,问最早什么时候薯片能被吃完。

题目分析

这道题给定三个人吃薯片的时间间隔 t1t2t3,以及薯片总数 n,要求最早什么时候薯片能被吃完。肯定依旧是通过二分查找来找到满足不等式 ⌊ t / t 1 ⌋ + ⌊ t / t 2 ⌋ + ⌊ t / t 3 ⌋ ≥ n ⌊t/t1⌋ + ⌊t/t2⌋ + ⌊t/t3⌋ ≥ n ⌊t/t1⌋+⌊t/t2⌋+⌊t/t3⌋≥n的最小 t 值。

c 复制代码
#include <stdio.h>

// 计算在时间t内三人吃的薯片总数
int total(int t, int t1, int t2, int t3)
 {
    return (t / t1) + (t / t2) + (t / t3);
}

// 使用二分查找找到最早吃完薯片的时间
int time(int t1, int t2, int t3, int n) {
    int left = 1;
    int right = n * (t1 < t2? t1 : t2) < t3? n * (t1 < t2? t1 : t2) : t3;
    while (left < right) {
        int mid = left + (right - left) / 2;
        if (total(mid, t1, t2, t3) >= n) {
            right = mid;
        } else {
            left = mid + 1;
        }
    }
    return left;
}

int main() {
    int t1, t2, t3, n;
    scanf("%d %d %d %d", &t1, &t2, &t3, &n);
    int a = time(t1, t2, t3, n);
    printf("%d\n", a);
    return 0;
}

我首先计算在时间 t 内三人吃的薯片总数的函数,这里调用了 total,然后时间 t 和三个人吃薯片的时间间隔 t1t2t3 作为参数。通过 t / t1t / t2t / t3 分别计算在时间 t 内每个人吃的薯片数量(这里是向下取整的结果,因为在C语言中整数除法会自动向下取整 ),然后将三人吃的薯片数量相加并返回。使用二分查找找到最早吃完薯片时间的函数 time

依然按照套路,初始化二分查找的左边界 left 为1,表示最早可能吃完的时间是1秒。右边界 right 初始化为 n * (t1 < t2? t1 : t2) < t3? n * (t1 < t2? t1 : t2) : t3,这是一个估计的上限,取三人中最小时间间隔的 n 倍和 t3 中的较小值,这样可以保证在这个范围内一定能找到答案(如果时间超过这个上限,即使是吃的最快的人单独吃 n 个薯片也足够了)。

计算中间时间,然后调用 total 函数计算在中间时间 mid 内三人吃的薯片总数,并与 n 进行比较。如果吃的薯片总数大于等于 n,说明可能在更早的时间就吃完了,将右边界 right 更新为 mid;否则,说明时间不够,需要增加时间,将左边界 left 更新为 mid + 1。当 leftright 相等时,二分查找结束,返回 left 作为最早吃完薯片的时间。最后在主函数里面输出调用就行。

K 小鸟游的寒假

题目大意

给定三个长度为 n n n 的数组 a , b , c a, b, c a,b,c,分别表示在第 i i i 天和六花一起吃饭、看电影、玩桌游的朋友人数。每一天只能选择一个活动。

请从这三个数组中选择三天 x , y , z x, y, z x,y,z,使得 a x + b y + c z a_x + b_y + c_z ax+by+cz 最大。

题目分析

这道题给定三个长度为 n 的数组 abc,分别表示每天不同活动的朋友人数,要求从三个数组中选择三天,使得对应活动的朋友人数之和最大,且三天不能重复。

c 复制代码
#include <stdio.h>

// 找到数组中的最大值、次大值和第三大值的索引
void find(int arr[], int n, int *A, int *B, int *C) {
    int a = -1, b = -1, c = -1;
    for (int i = 0; i < n; i++) 
    {
    
        if (arr[i] > a)
         {
            c = b;
            b = a;
            a = arr[i];
            *C = *B;
            *B = *A;
            *A = i;
            
        } 
        
        else if (arr[i] >b) {
            c = b;
            b = arr[i];
            *C = *B;
            *B = i;
        } 
        else if (arr[i] > c) {
            c = arr[i];
            *C = i;
        }
    }
}

找到数组中的最大值、次大值和次次大值索引的函数 find。数组 arr 和数组长度 n,以及三个指针 用于返回最大值、次大值和次次大值的索引。初始化 abc 为 -1,表示初始没有找到最大值。遍历数组,对于每个元素 arr[i]:如果 arr[i] 大于当前最大值 a,则更新最大值、次大值和次次大值及其索引。将原来的最大值 a 变为次大值 b,原来的次大值 b 变为次次大值 c,并更新相应的索引。如果 arr[i] 大于当前次大值 b,则更新次大值和次次大值及其索引。如果 arr[i] 大于当前次次大值 c,则更新次次大值及其索引。

L 白小藜和合数

题目大意

给你 n n n 和 d d d,构造一个长度为 n n n、公差为 d d d,且各项都是合数的等差数列。

题目分析

这道题要求构造一个长度为 n、公差为 d,且各项都是合数的等差数列。根据题解思路,利用 d 的倍数来构造这个数列,从 2d 开始,到 (n + 1)d 结束,这样可以保证数列中的数除了 d 本身(当 d 为质数时),其他都是合数。

c 复制代码
#include <stdio.h>

void con(int n, int d) {
    for (int i = 2; i <= n + 1; i++) {
        printf("%d ", i * d);
    }
}

int main() {
    int n, d;
    scanf("%d %d", &n, &d);
    con(n, d);
    return 0;
}

构造并输出全是合数的等差数列的函数 con,两个参数 nd,分别表示数列的长度和公差。使用 for 循环从 2n + 1,对于每个 i,输出 i * d,这样就构造出了从 2d(n + 1)d 的数列,满足各项都是合数(除了 d 可能为质数的情况,但题目要求构造的数列满足条件即可,不要求证明每个数都是合数)。

相关推荐
励志要当大牛的小白菜4 分钟前
ART配对软件使用
开发语言·c++·qt·算法
qq_513970447 分钟前
力扣 hot100 Day56
算法·leetcode
PAK向日葵1 小时前
【算法导论】如何攻克一道Hard难度的LeetCode题?以「寻找两个正序数组的中位数」为例
c++·算法·面试
爱装代码的小瓶子2 小时前
数据结构之队列(C语言)
c语言·开发语言·数据结构
爱喝矿泉水的猛男3 小时前
非定长滑动窗口(持续更新)
算法·leetcode·职场和发展
YuTaoShao3 小时前
【LeetCode 热题 100】131. 分割回文串——回溯
java·算法·leetcode·深度优先
YouQian7724 小时前
Traffic Lights set的使用
算法
快乐飒男4 小时前
哈希表(c语言)
c语言·哈希算法·散列表
go54631584655 小时前
基于深度学习的食管癌右喉返神经旁淋巴结预测系统研究
图像处理·人工智能·深度学习·神经网络·算法
aramae5 小时前
大话数据结构之<队列>
c语言·开发语言·数据结构·算法