bupt2024大一上第三次机考

目录

6-1 集合添加

函数接口定义:

裁判测试程序样例:

输入样例:

输出样例:

answer:

思路:

6-2 回文单词

函数接口定义:

裁判测试程序样例:

输入样例:

输出样例:

answer:

 思路:

6-3 递归输出三角形

函数接口定义:

裁判测试程序样例:

输入样例:

输出样例:

answer:

思路:

7-1 抽奖

输入格式:

输出格式:

输入样例:

输出样例:

answer:

思路:

7-2 古代密码(史中史,我宣布没有哪一题比这更史)

输入格式:

输出格式:

输入样例:

输出样例:

answer:

思路:


 

点评:史中史

6-1 集合添加

分数 100

 

全屏浏览

 

切换布局

作者 scs

单位 北京邮电大学

集合,简称集,是数学中一个基本概念,也是集合论的主要研究对象。集合论的基本理论创立于19世纪,关于集合的最简单的说法就是在朴素集合论(最原始的集合论)中的定义,即集合是“确定的一堆东西”,集合里的“东西”则称为元素。现代的集合一般被定义为:由一个或多个确定的元素所构成的整体 。集合有一个非常重要的性质叫互异性,它指的是在一个集合中,任何两个元素都认为是不相同的,即每个元素只能出现一次。因此,在程序设计中,当我们向一个集合中添加新的元素时,如果该元素没有在集合中,则会将该元素添加到集合中去;如果该元素已经在集合中了,则该元素不会再次被添加到集合中,也就是说原集合保持不变。现在就请你写一个函数来模拟集合的添加操作。

输入格式:
只有一行,为若干用空格分隔的整数,这些整数最后一个数字一定是-1,且其它数字一定不是-1。除了-1外,其它整数将依次被添加到集合中。
输出格式:
也只有一行,为若干用空格分隔的整数,代表当前集合内所有元素(初始结合为空集,输出时按添加次序输出)。

函数接口定义:

int    put(int set[] , int length , int element);

其中 setlengthelement 都是用户传入的参数。 set 为存放集合元素的数组; length代表当前集合内元素的个数; element 代表将要添加到集合中的新元素。函数须返回添加后集合内元素的个数。添加规则:如果element 不在 set中,则element将被保存到set中所有已有元素的后边且中间不能有空位置。也就是说所有元素是按添加顺序一个挨一个存放的。

裁判测试程序样例:

#include<stdio.h>

#define        MAXLEN        100

int    put(int set[] , int length , int element);

int main()
{
    int        i , num , set[MAXLEN];
    int        len = 0 ;

    scanf( "%d" , &num ) ;
    while ( num != -1 ){
        len = put(set , len , num);
        scanf( "%d" , &num ) ;
    }
    for (i = 0 ; i < len - 1 ; i++)
        printf( "%d " , set[i] ) ;
    printf( "%d\n" , set[i] ) ;
    
    return 0;
}

/* 请在这里填写答案 */

输入样例:

1 2 2 3 3 3 4 4 4 4 -1

输出样例:

1 2 3 4

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

answer:

int    put(int set[] , int length , int element)
{
    int flag = 0;
    for(int i = 0; i < length; i++)
    {
        if(set[i] == element)
        {
            flag = 1;
            break;
        }
    }

    if(flag == 0)
    {
        set[length] = element;
        length++;
    }

    return length;
}

思路:

大概就是遍历整个数组,如果找到了就可以简单终止,如果整个字符串都没有找到目标元素的话就将这个元素插入进去。

 

6-2 回文单词

分数 100

 

全屏浏览

 

切换布局

作者 scs

单位 北京邮电大学

回文单词是指正着读和反着读都一样的单词,比如deed,level等等。现在请你写一个函数来判断一个字符串在去掉干扰后是不是回文单词。这里干扰指的是输入的字符串中除了英文小写字母外其它字符都是干扰。你的函数首先要去掉这些干扰字符(且保持小写字母原有顺序不变),然后再判断剩下的单词是否为回文单词。
输入格式:
只有一行,为一个长度不超过100且只包含英文大小写字母和数字的字符串。
输出格式:
也只有一行,格式见裁判测试程序样例中的代码。

函数接口定义:

int    isPalindrome(char word[]);

其中 word 为待处理单词,去掉干扰后的单词仍保存在word中。如果 word 去掉干扰后为回文单词,则函数须返回 1,否则返回0。

裁判测试程序样例:

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

#define        MAXLEN        100

int    isPalindrome(char word[]);

int main()
{
    char    word[MAXLEN];

    scanf( "%s" , &word ) ;
    if (isPalindrome(word))
        printf( "%s is a palindrome.\n" , word ) ;
    else
        printf( "%s is not a palindrome.\n" , word ) ; 
    
    return 0;
}

/* 请在这里填写答案 */

输入样例:

DEdeEDed00

输出样例:

deed is a palindrome.

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

answer:

int    isPalindrome(char word[])
{
    int len = strlen(word);

    for(int i = 0; i < len; i++)
    {
        if(word[i] >= 'a'&&word[i] <= 'z');
        else
        {
            for(int j = i; j < len; j++)
            {
                word[j] = word[j + 1];
            }
            i--;
            len--;
        }
    }

    for(int n; n <= len/2 - 1; n++)
    {
        if(word[n] != word[len - 1 - n])
            return 0;
    }

    return 1;
}

 思路:

把不符合的字符删除就可以了,然后加上一个是不是回文字符串的判定就行了(这个是比较基础的东西,从左右两边分别逼近就行了)

6-3 递归输出三角形

分数 100

 

全屏浏览

 

切换布局

作者 scs

单位 北京邮电大学

请设计一个递归函数,该函数的功能为按要求输出一个数字三角形。

输入格式:
只有一行为一个整数n(0<n<100),代表数字三角形的阶。

输出格式:
共n行,第一行为一个1,第二行为两个2,第三行为三个3,依此类推。数字之间用空格分隔,行末无空格,为换行符。样例为6阶数字三角形。

特别提醒:本题要求递归求解,不允许使用全局变量、静态变量等;不允许使用while、do while、for、goto等结构;不允许打表等方式解题;否则没有分,但可以自己定义函数。

函数接口定义:

void    output( int n ) ;

其中 n 是用户传入的参数,代表三角形的阶。 函数没有返回值。

裁判测试程序样例:

#include <stdio.h>

void    output( int n ) ;

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

/* 请在这里填写答案 */

输入样例:

6

输出样例:

1
2 2
3 3 3
4 4 4 4
5 5 5 5 5
6 6 6 6 6 6

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

answer:

void    output( int n )
{
    if(n > 1)
    {
        output(n - 1);
    }
    Print(n, n);
}

void Print(int n, int i)
{
    if(i == 1)
    {
        printf("%d\n", n);
    }
    else if(i > 1)
    {
        printf("%d ", n);
        return Print(n, i - 1);
    }
}

思路:

不让用for,while等等是什么🐣,我想不出来真的,还是大佬指点;

Print就是负责打印n个n;

output有点难想,建议对着代码在草稿纸上画画过程;

 

7-1 抽奖

分数 100

 

全屏浏览

 

切换布局

作者 scs

单位 北京邮电大学

年会中,抽奖环节无疑是备受期待的重头戏。只是今年的抽奖方式有些特别。入场时,大家会随机抽取一张带有独特整数的卡片,而各个奖项的中奖号码会提前公布在大屏幕上。但别以为手中的号码和中奖号码一样就能中奖,真正的获奖条件是:必须找到另一个人,两人手中卡片数字相加等于中奖号码,则表明两个人同时中奖。起初,大家只把这规则当作新奇小游戏,未察觉其中难度。抽奖开启,大家才发现要确定自己是否中奖是一件很困难的事儿。现在就请聪明的你写一段程序来帮助大家找到中奖者。

输入格式:

第一行为一个整数n(1<n<100000),代表参与抽奖的人数;第二行为n个用空格分隔的整数,代表每个人手里的号码;第三行为一个整数m(1<m<50),代表共m个奖项;第四行为m个用空格分隔的整数,代表每个奖项的号码。
测试用例保证:
1、第二行n个数字互不相同且按升序排列;
2、所有整数可以用int存储;
3、每个奖项有且仅有两人(惟一一对)获奖。

输出格式:

共m行,每行依次对应输入的奖项号码,格式为 A = B + C(具体见样例),其中A代表奖项号码,B和C代表中奖人号码且B小于C。

输入样例:

9
15 25 27 32 33 64 73 76 98
5
162 88 79 100 123

输出样例:

162 = 64 + 98
88 = 15 + 73
79 = 15 + 64
100 = 27 + 73
123 = 25 + 98

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

栈限制

8192 KB

answer:

#include <stdio.h>

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

    return -1;
}

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

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

    int m;
    scanf("%d", &m);

    int arr2[50];
    for(int i = 0; i < m; i++)
    {
        scanf("%d", &arr2[i]);
    }

    int num, flag, target;
    for(int i = 0; i < m; i++)
    {
        num = arr2[i];
        for(int j = 0; j < n; j++)
        {
            target = num - arr1[j];
            flag = findfun(arr1, j , n, target);
            if(flag != -1)
            {
                printf("%d = %d + %d\n", num, arr1[j], arr1[flag]);
                break;
            }
        }
    }

    return 0;
}

思路:

最出生🐣的一题:聆听超时破碎的声音;

后面一坨400ms我还以为我是有什么语法错误🐣,原来是后面一坨超级数据大的要死;

使用二分查找就可以解决这个问题,而且只需要二分C的号码出来就行了;

findfun函数就是把值位target的数字下标找到,如果没有就返回-1(为什么不返回0?如果arr1[0]+arr1[0]。。。。)

当然也可以参考力扣第一题官方解答哈希表:

1. 两数之和 - 力扣(LeetCode)1. 两数之和 - 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target  的那 两个 整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。你可以按任意顺序返回答案。 示例 1:输入:nums = [2,7,11,15], target = 9输出:[0,1]解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。示例 2:输入:nums = [3,2,4], target = 6输出:[1,2]示例 3:输入:nums = [3,3], target = 6输出:[0,1] 提示: * 2 <= nums.length <= 104 * -109 <= nums[i] <= 109 * -109 <= target <= 109 * 只会存在一个有效答案 进阶:你可以想出一个时间复杂度小于 O(n2) 的算法吗?https://leetcode.cn/problems/two-sum/description/我不是大佬就不说多了:(

7-2 古代密码(史中史,我宣布没有哪一题比这更史)

分数 100

 

全屏浏览

 

切换布局

作者 scs

单位 北京邮电大学

古罗马帝国有一个拥有各种部门的强大政府组织。其中一个部门就是保密服务部门。为了保险起见,在省与省之间传递的重要文件中的大写字母是加密的。当时最流行的加密方法是替换和重新排列。

替换方法是将所有出现的字符替换成其它的字符。有些字符会替换成它自己。例如:替换规则可以是将'A' 到 'Y'替换成它的下一个字符,将'Z'替换成 'A',如果原词是 "VICTORIOUS" 则它变成 "WJDUPSJPVT"。

排列方法改变原来单词中字母的顺序。例如:将顺序 < 2 1 5 4 3 7 6 10 9 8 > 应用到 "VICTORIOUS" 上,则得到"IVOTCIRSUO"。

人们很快意识到单独应用替换方法或排列方法加密,都是很不保险的。但是如果结合这两种方法,在当时就可以得到非常可靠的加密方法。所以,很多重要信息先使用替换方法加密,再将加密的结果用排列的方法加密。用两种方法结合就可以将"VICTORIOUS" 加密成"JWPUDJSTVP"。

考古学家最近在一个石台上发现了一些信息。初看起来它们毫无意义,所以有人设想它们可能是用替换和排列的方法被加密了。人们试着解读了石台上的密码,现在他们想检查解读的是否正确。他们需要一个计算机程序来验证,你的任务就是写这个验证程序。

输入格式:

输入有两行。第一行是石台上的文字。文字中没有空格,并且只有大写英文字母。第二行是被解读出来的加密前的文字。第二行也是由大写英文字母构成的。
两行字符数目的长度都不超过100。

输出格式:

如果第二行经过某种加密方法后可以产生第一行的信息,输出 "YES",否则输出"NO"。

输入样例:

JWPUDJSTVP
VICTORIOUS

输出样例:

YES

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

栈限制

8192 KB

answer:

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

void Sort(int a[], int n)
{
    int i, j, temp;
    for(i = 1; i <= n -1; i++)
    {
        for(j = 0; j <= n - i - 1; j++)
        {
            if(a[j] > a[j + 1])
            {
                temp = a[j];
                a[j] = a[j + 1];
                a[j + 1] = temp;
            }
        }
    }
}

int main()
{
    char ch1[101] = {0};
    char ch2[101] = {0};
    int word1[26] = {0};
    int word2[26] = {0};
    scanf("%s", ch1);
    scanf("%s", ch2);

    int len1 = strlen(ch1);
    int len2 = strlen(ch2);
    
    for(int i = 0; i < len1; i++)
    {
        int a = ch1[i] - 'A';
        word1[a]++;
    }
    for(int j = 0; j < len2; j++)
    {
        int b = ch2[j] - 'A';
        word2[b]++;
    }

    Sort(word1, 26);
    Sort(word2, 26);

    for(int n = 0; n < 26; n++)
    {
        if(word1[n] != word2[n])
        {
            printf("NO\n");
            return 0;
        }
    }

    printf("YES\n");

    return 0;
}

思路:

正常人真的有思路吗(疑惑😀),史中史;

这题目困惑人,完全不懂;

据大佬指点,只需要每个字母次数相同就行了,如:字符串A:aabbbc和字符串B:eejjq就满足,你做的就是判断a出现了2次,那字符串B中有没有一种字母出现了两次,然后琢磨代码吧🤣;

 

大佬们理性讨论哈!!!!我是小白求带🙏

 

 

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值