bupt 2024大一上第二次机考

目录

6-1数字判断

函数接口定义:

裁判测试程序样例:

输入样例:

输出样例:

answer1:

answer2:

 6-2 数制

函数接口定义:

裁判测试程序样例:

输入样例:

输出样例:

answer:

7-1回文数2 

输入格式:

输出格式:

输入样例一:

输出样例一:

输入样例二:

输出样例二:

answer:

 7-2第十届黄龙市杯世界女子围棋赛

输入格式:

输出格式:

输入样例:

输出样例:

 answer:

7-3乘车 

输入格式:

输出格式:

输入样例:

输出样例:

answer: 

7-4账单 

输入格式:

输出格式:

输入样例:

输出样例:

answer:

7-5贴邮票一

输入格式:

输出格式:

输入样例:

输出样例:

answer:


6-1数字判断

分数 100

全屏浏览

切换布局

作者 scs

单位 北京邮电大学

请写一个函数,该函数可以判断一个非负整数的每一位数字是不是从右到左严格递增的。比如54321即满足这个条件;但221就不满足。
特别提醒,如果一个非负整数只有1位我们认为它是严格递增的。

输入格式
第1行是一个正整数n( (n < 30),后面跟着n行输入,每行一个整数,代表n个待判断的非负整数。测试用例保证合法且所有整数都可以用int存储。
输出格式
输出包含n行,每行都是一个整数,依此对应输入中n个待判断的非负整数的判断结果(函数返回值)。

函数接口定义:

int judge( int n );

其中 n 是用户传入的参数,代表待判断整数。当n 是从右到左严格递增时函数须返回 0,否则函数返回从右到左第一次违反严格递增的那个数字的位数(个位为第1位,十位为第2位,依此类推)。

裁判测试程序样例:

#include<stdio.h>

int    judge(int) ;

int    main()
{ 
    int        i , n , num;

    scanf( "%d" , &n ); 
    for ( i = 0 ; i < n ; i++ )
    {
        scanf( "%d" , &num );
        printf( "%d\n" ,  judge(num) ); 
    }

    return 0 ;
}

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

输入样例:

2
12345
54321

输出样例:

2
0

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

answer1:

int judge(int n)
{
    int number = n;

    int len = 0;
    while(number != 0)
    {
        len++;
        number = number / 10;
    }

    int flag = 1;
    int i = 1;
    if(len == 1)
    {
        return 0;
    }
    else
    {
    while((n / 10) != 0)
    {
        int a = n % 10;
        n = n / 10;
        int b = n % 10;
        i++;
        if(a >= b)
        {
            flag = 0;
            return i;
        }
    }
        if(flag == 1) return 0;
    }
}

ps:感觉我用一个求数字位数的函数只为了判断是否是1位数是小题大做,简直是太蠢了,不妨用n/10是否为0来就行判断,和后面也有呼应一点

answer2:

int judge(int n)
{

    int flag = 1;
    int i = 1;

    if((n / 10) == 0)
    {
        return 0;
    }
    else
    {
    while((n / 10) != 0)
    {
        int a = n % 10;
        n = n / 10;
        int b = n % 10;
        i++;
        if(a >= b)
        {
            flag = 0;
            return i;
        }
    }
        if(flag == 1) return 0;
    }
}

 6-2 数制

记数是人类用来表示和计算数量的基本方法。在记数过程中,我们通常使用一系列有序的符号或数字来表示数量。这些符号或数字可以是简单的(如手指计数),也可以是复杂的(如现代数学中的数字系统)。这里有一个非常重要的概念就是数制。数制中表示数值大小的那些固定的数字符号称为数码。每种数制所使用数码的个数称为该进制数的基数。比如十进制的基数为10,二进制的基数为2。一个数码处在不同位置上所代表的值不 同,每个数码所表示的数值等于该数码乘以一个与数码所在位置相关的常数,这个常数叫做位权。位权的大小是以该数制的基数为底、数码所在位置的序号为指数的整数次幂。例如:二进制数101,左边的数码1的位权是22,中间的数码0的位权是21,右边的数码1的位权是20。十进制数12.1,小数点前面的数码1的位权是101,数码2的位权是100,小数点后面的数码1的位权是10−1。
事实上对于任意一个R进制数都可以表示为该数制的数码与基数的幂次的乘积之和,即对任意的R进制数an−1​an−2​…a1​a0​a−1​a−2​…a−m​,都可以表示成按位权展开的多项式之和的形式:an−1​×Rn−1+an−2​×Rn−2+…+a1​×R1+a0​×R0+a−1​×R−1+a−2​×R−2+…+a−m​×R−m。其中,R是数制的基数,ai​ (i = -m,…,-2,-1,0,1.,…,n-1) 为该数制的数码,n为该R进制数的整数部分的位数,m为小数部分的位数。
尽管不同进制在表示数值时使用的数字和进位规则不同,但它们都可以表示相同的数值范围,只是表示方式和长度不同。因此,在理论上讲,各种进制是等价的。
现给定十进制正整数,和一个进制的基数(10进制表示),请你写一个函数将这个正整数变为该进制的数码与基数的幂次的乘积之和。

输入:
第一行为一个整数T(0<T<100),代表共T组测试用例。后边是T行,每行均为两个用一个空格分隔的整数,依次代表待处理十进制整数n(0<n<100000000),和基数base(1<base<100)。测试用例保证合法。
输出:
若干行,每组测试用例的格式都是一样的,先输出测试用例的序号(见输出样例),然后幂次从小到大的顺序输出多项式中每一项的数码和权值(用一个空格分隔),每行输出一项(具体见输出样例),如果数码为0,则不输出该项。
样例解释:
第一组测试用例,10进制整数12345可以表示为 5×100+4×101+3×102+2×103+1×104 ,即 12345 = 5 + 40 + 300 + 2000 + 10000 。
第二组测试用例,10进制整数12345可以表示为 1×20+1×23+1×24+1×25+1×212+1×213 (1 ,2,6,7,8 ,9 ,10,11次幂所乘的数码均为0,所以没有输出), 即12345 = 1 + 8 + 16 + 32 + 4096 + 8192 。(特别的,由于二进制的数码只有0和1两个,因此任意一个正整数都可以惟一的表示为若干个2的幂次之和。)

函数接口定义:

void    printBasePower( int number , int base ) ;

其中 numberbase 都是用户传入的参数。number 代表待处理10进制正整数; base 是进制的基数。函数没有返回值,但要按要求输出结果。

裁判测试程序样例:

#include <stdio.h>

void    printBasePower( int number , int base ) ;

int main()
{
    int        i , T , n , base ;
    
    scanf( "%d" , &T ) ;
    for ( i = 1 ; i <= T ; i++ )
    {
        scanf( "%d%d" ,  &n , &base ) ;
        printf("Test Cases %d :\n" , i ) ;
        printBasePower( n , base ) ;
    }
    
    return 0;
}

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

输入样例:

2
12345 10
12345 2

输出样例:

Test Cases 1 :
5 1
4 10
3 100
2 1000
1 10000
Test Cases 2 :
1 1
1 8
1 16
1 32
1 4096
1 8192

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

answer:

#include <math.h>

void printBasePower(int number, int base)
{
    int i = 0, a;
    while(number != 0)
    {
        a = number % base;
        if(a != 0)
        {
            printf("%d %d\n", a, (int)pow(base, i));
        }
        number = number / base;
        i++;
    }
    
    return 0;
}

上机考试没有做出来啊🤔,对这个数制的概念和计算不太熟悉😂。

那数制的转换是个什么东西呢?

对于题目给的整数就可以采用(举例十进制转二进制)

1. 莽莽除(除二取余法,短除法)

  • 原理
    这是最基础且常用的手动转换方法。其依据是二进制数的基数为 2,所以不断地用十进制数除以 2,记录每次除法运算得到的余数(余数只会是 0 或 1,这恰好是二进制的数码),一直除到商为 0 为止。最后把所有余数按照从下往上(也就是从后往前记录的顺序)排列起来,所得到的序列就是对应的二进制数。
  • 示例
    把十进制数 10 转换为二进制数,步骤如下:
    • 10÷2 = 5,余数为 0
    • 5÷2 = 2,余数为 1
    • 2÷2 = 1,余数为 0
    • 1÷2 = 0,余数为 1
      从下往上排列余数,得到二进制数 1010。

2. 按位权展开法(不太清楚怎么实现代码)

  • 原理
    对于一个十进制数,我们知道它可以按位权展开为各个数位上的数字乘以对应位权(以 10 为底的幂次)之和的形式,例如十进制数 123 可以写成 1×10² + 2×10¹ + 3×10⁰。而要转换为二进制,我们需要找到对应的以 2 为底的幂次组合,使得其和等于该十进制数。从最高位开始尝试,找到满足条件的二进制位上的数码(0 或 1)。
  • 示例
    将十进制数 13 转换为二进制数,过程如下:
    首先,确定二进制数可能的最大位权,对于较小的数可以从 2ⁿn 依次递减)开始尝试,找到小于等于该十进制数的最大的 2ⁿ
    2³ = 813 - 8 = 5;此时确定二进制数从左数第 4 位(最高位)为 1(因为有一个 8)。
    接着,看 2² = 45 - 4 = 1,确定从左数第 3 位为 1
    再看 2¹ = 21 < 2,所以从左数第 2 位为 0
    最后,2⁰ = 1,刚好剩下 1,所以从左数第 1 位(最低位)为 1
    组合起来得到二进制数 1101

7-1回文数2 

输入任意整数,设计一个回文数判定算法,判定并输出该数是否为回文数?

输入格式:

只有一行,为两个用空格分隔的正整数num及len。它们分别代表输入的整数及其长度(0<len<10)。

输出格式:

前边若干行按比较顺序依次输出每行为参与比较的两个数(中间有一个空格),高位在前,低位在后。如果len为奇数,最后一次只有一个数字时,则将该数字输出2次。如果没有比较完就已知道不是回文数,要停止比较,后边的比较过程没有了,也就没有相应的输出。
最后一行:如果是回文数则输出Yes,否则输出No。

输入样例一:

121 3

输出样例一:

1 1
2 2
Yes

输入样例二:

1234 4

输出样例二:

1 4
No

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

栈限制

8192 KB

answer:

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

int main()
{
    int flag = 1;
    int len , number;
    scanf("%d %d", &number, &len);
    for(int i = len -1; i >= 0; i = i-2)
    {
        int a = number / pow(10,i);
        int b = number % 10;
        printf("%d %d\n", a, b);
        if(a != b) 
        {
            printf("No\n");
            flag = 0;
            break;
        }
        number = (number % (int)pow(10,i))/10;
    }
    if(flag)
    {
    printf("Yes\n");
    }
    
    return 0;
}

机考的时候想到的,现在来看甚至想不太清楚了!

我的想法是用一个和位数相关的值 i 来判断是否继续进行循环 ,因为它终止前一次i必然是0或者1,在进行一次i-2就是负数了;

有些测试样例还可以用n!=0判断,但是像这样的101,10201就不能判断了;

 7-2第十届黄龙市杯世界女子围棋赛

第十届黄龙士杯世界女子围棋赛是由中国围棋协会、泰州市体育局、姜堰区人民政府主办的围棋赛事。 2024年6月27日,2024年中国姜堰第十届黄龙士杯世界女子围棋赛第七轮即最后一轮比赛在江苏省泰州市姜堰溱湖会展中心结束。四位中国棋手在面对日韩对手的比赛中全部获胜,其中周泓余以6胜1负夺得冠军,日本棋手上野爱咲美以5胜2负获得亚军。
该项赛事采用单循环赛制,8位棋手通过七轮单循环赛决出冠亚军。成绩计算的规则为:

  1. 每局胜者记2分,负者记0分。如遇三劫循环等特例,该局按和棋处理,每人记1分。
  2. 积分高者名次列前,如遇积分相同,依次比较:所胜对手积分、直胜。
  3. 如以上办法不能决出冠亚军,则采用抽签定位方式加赛快棋,用时方式为每方3次30秒读秒。其他名次允许并列。

现在我们假设共有6人(A、B、C、D、E和F,也就是说共5轮比赛)参加比赛,比赛中没有出现和棋,且她们每人的获胜盘数都不相同。其中A获胜局数为X,B获胜局数为Y,请写一段程序输出所有可能的名次。

输入格式:

只有一行,为两个用空格分隔的整数。依次代表X和Y。测试用例保证合法。

输出格式:

若干行,每行均为6个用空格分隔的整数,依次代表A的名次,B的名次,C的名次,D的名次,E的名次,F的名次。每种可能的名次输出时首先按照A名次从小到大输出;当A名次相同时,按照B名次从小到大输出;依此类推,后边排序的优先顺序依次为C、D、E、F。具体可参考输出样例。

输入样例:

5 4

输出样例:

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

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

栈限制

8192 KB

 answer:

#include <stdio.h>

int Rank(int n)
{
    switch(n)
    {
        case 0:
            return 6;
        case 1:
            return 5;
        case 2:
            return 4;
        case 3:
            return 3;
        case 4:
            return 2;
        case 5:
            return 1;
    }
}

int main()
{
    int a, b;
    scanf("%d %d", &a, &b);
    
     for(int c = 5; c >= 0; c--)
     {
        for(int d = 5; d >= 0; d--)
        {
            for(int e = 5; e >= 0; e--)
            {
                for(int f = 5; f >= 0; f--)
                {
                if((a + b + c + d + e + f )== 15&&c!=a&&c!=b&&d!=a&&d!=b&&d!=c&&e!=a&&e!=b&&e!=c&&e!=d&&f!=a&&f!=b&&f!=c&&f!=d&&f!=e)
                {
                    printf("%d %d %d %d %d %d\n", Rank(a), Rank(b), Rank(c), Rank(d), Rank(e), Rank(f));
                }
                }
            }
        }
     }
    return 0;
}

对于这个题目我也没有什么简化的想法......可以套用练习题里面的计算每个人获胜的局数的代码,小小计算一下总共十五局。再用一个子函数把局数换算成名次。最难搞的是哪个判断两两不等,想不到,只好莽莽打字💔。

7-3乘车 

火车从始发站(称为第1站)开出,在始发站上车的人数为 departureStation ,然后到达第2站,在第2站有人上、下车,但上、下车的人数相同,因此在第2站开出时(即在到达第3站之前)车上的人数保持为departureStation人。从第3站起(包括第3站)上、下车的人数有一定的规律,即上车的人数都是前两站上车人数之和,而下车人数等于上一站上车人数,一直到终点站的前一站(第 n -1站),都满足此规律。
现给出的条件是共有 n 个车站,始发站上车的人数为 departureStation ,最后一站下车的人数是 m (全部下车)。请你写一段程序算出第2站上车的人数。
样例解释:

各站情况如下:
车站编号:   1   2   3   4   5   6   7   8   9  10
上车人数:  15  20  35  55  90 145 235 380 615   0
下车人数:   0  20  20  35  55  90 145 235 380 610
车上人数:  15  15  30  50  85 140 230 375 610   0

输入格式:

只有一行,为三个用空格分隔的整数,依次代表n(n > 3) , departureStation 和 m。
测试用例保证:1、输入一定合法;2、计算过程中所有整数都可以用int存储;3、一定有解。

输出格式:

只有一行,为一个整数,代表第2站上车的人数。

输入样例:

10 15 610

输出样例:

20

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

栈限制

8192 KB

answer: 

#include <stdio.h>

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

    int flag = 0, up1, up2, down1, down2;
    int up = 0, down = 0, x = 0;
    for(x; !flag; x++)
    {
        up1 = departureStation;
        up2 = x;
        down1 = 0;
        down2 = x;
        up = up1 + up2;
        down = down1 + down2;
        for(int i = 3; i < n; i++)
        {
            int temp = up2;
            up2 = up1 + up2;
            up1 = temp;
            up += up2;
            down2 = temp;
            down += down2;
            if((up - down) == m) flag = 1;
        }
    }
    printf("%d", x-1);

    return 0;
}

可以看作是一个解方程的问题;

上车人数实际上就是一个特殊的兔子数列,我们要求的就是求这个数列的第二项;

按题目所给的关系进行求解就可以了;

最后一部flag为1时x也会再次加1,所以再printf中使用x-1解决误差;

7-4账单 

在双十一期间,小伙伴们的宿舍迅速变成了一片“快递的海洋”,每个角落都堆满了等待被拆开的“幸福彩蛋”。而当双十一的热度尚未完全消散时,小明就收到了一份特别的“豪华惊喜”——他的购物账单。现在请你写一段程序帮小明计算一下他一共花了多少钱。

输入格式:

只有一行,为长度不超过100000的字符串,代表小明的账单。字符串内只包含英文小写字母和数字,其中小写字母代表物品名称,数字代表钱数(均为正整数)。账单中所有整数的和即为小明所花钱数。测试用例保证合法且所有整数可以用int存储。

输出格式:

只有一行,为一个整数,代表小明所花钱数。

输入样例:

ebook17papertowels18headphones179laptopbag49wirelesscharger75

输出样例:

338

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

栈限制

8192 KB

answer:

#include <stdio.h>
#define Letter 1
#define NUM 0

int main()
{
    char ch;
    int date, sum = 0;
    int state = Letter;

    while((ch = getchar())!='\n')
    {
        switch(state)
        {
            case Letter:
                if(ch >= '0'&&ch <= '9')
                {
                    date = ch - '0';
                    state = NUM;
                }
                break;
            case NUM:
                if(ch >= '0'&&ch <= '9')
                {
                    date = date * 10 + (ch - '0');
                }
                else
                {
                    sum += date;
                    state = Letter;
                }
                break;
        }
    }
    if(state == NUM)
    {
        sum += date;
    }
    printf("%d\n", sum);
    return 0;
}

状态机类型的题目;

需要处理最后的数字部分;

注意终止条件的判断'\';

7-5贴邮票一

现在有两种面值的邮票,一种为8角,一种为6角。你要付n角的邮资(不能多付也不能少付),请给出邮票张数最少的方案。如果没有正好的方案则输出-1。

输入格式:

只有一行,为若干个整数(至少有两个)。这些整数最后一个整数一定是-1(输入结束标志,无需处理),其他整数均大于0,这些大于0的整数代表邮资。

输出格式:

若干行,每行依次对应输入的一个邮资,如果该邮资有正好的方案,则为两个用空格分隔的整数,代表张数最少的方案。前边的数字代表需要的8角的邮票的张数,后边的数字代表6角的邮票的张数;如果该邮资没有正好的方案则输出-1。测试用例保证所有整数均可以用int存储。。

输入样例:

24 14 11 -1

输出样例:

3 0
1 1
-1

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

栈限制

8192 KB

answer:

#include <stdio.h>

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

    while(n != -1)
    {
        find = 0;
        for(int i = n/8; i >= 0&&!find; i--)
        {
            for(int j = 0; j <= n/6&&!find; j++)
            {
                if(8*i + 6*j == n)
                {
                    find = 1;
                    printf("%d %d\n", i, j);
                }
            }
        }
        if(!find) printf("-1\n");
        scanf("%d", &n);
    }
    return 0;
}

与上一题不一样;

上一题是输入一串终止是\n,这一题是输入一个判断一个,终止是-1;

采用了贪心算法;

要求最小,必然8角的要取最大的,6角取最小的,for循环的开始就是这样的;

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值