Bootstrap

PTA L1系列题解(C语言)(L1_041 -- L1_048)

L1-041 寻找250

题目内容:

解题思路:

本题主要难点在于输入,对于不确定长度的输入结束判定。

对于这个,可以利用getchar()判定每次输入,如果是 ' \n ' 就停止。

C代码展示:

#include <stdio.h>

int main()
{
	int a, k=0, i=1;
	
	do{
		scanf("%d", &a);
		if (a == 250 && k == 0) k = i;
		i++;
	}while(getchar() != '\n');
	printf("%d\n", k);
	
	return 0;
}

L1-042 日期格式化

题目内容:

解题思路:

本体较为简单,就只需要注意,月份和日期都是两位输出,要补0。

C代码展示:

#include <stdio.h>

int main()
{
	int m, d, y;
	scanf("%d-%d-%d", &m, &d, &y);
	printf("%d-%02d-%02d\n", y, m, d);
	
	return 0;
}

L1-043 阅览室

题目内容:

解题思路:

本题主要难点在于 过滤无效信息 和 计算阅读长度。

本题我采取的方法是,使用哈希表来进行每一本书的时间记录,当读入 ' S ' 时,将时间转化成分钟进行记录,若后续没有读到 ' E ' ,就不用管那个数据,若是没有 ' S ' 直接读到 ' E ' 可以增加一个判定哈希表该位是否为0。到此就可以处理第一个问题了。

针对第二个问题,将时间转换为分钟进行计算会相对方便些,然后对于00:00的时间在我的代码中会出现无法记录的问题,所以我在每个时间上 +1;

注意:测试点中存在 00:00 时来借阅的,要注意处理。

C代码展示:

#include <stdio.h>

int time_change(int h, int m) // 定义一个函数,用于将时间从小时和分钟转换为分钟数,并加一
{
	return h * 60 + m + 1;
}

int main() {
    int n, book[15][1005] = {{0}}; // 定义变量n(预约的数量),book数组(用于记录每个预约的开始时间),初始化为0
    int k, h, m, time = 0, cnt = 0; // 定义变量k(预约的编号),h(小时),m(分钟),time(总时间),cnt(计时的预约数量)
    char x; // 定义字符变量x,用于存储预约的类型('S'表示开始,'E'表示结束)

    scanf("%d", &n); // 读取预约的数量
    for (int i = 1; i <= n;) { // 循环读取每个预约的详细信息
        scanf("%d %c %d:%d", &k, &x, &h, &m); // 读取预约的编号、类型和时间
        if (k == 0) { // 如果预约类型为0,表示需要输出当前的总时间和每个预约所用的时间
            if (cnt != 0) printf("%d %.0f\n", cnt, 1.0 * time / cnt); // 输出计时的预约数量和平均时间
            else printf("0 0\n"); // 如果没有计时的预约,输出0 0
            i++; // 增加预约数量计数
            time = cnt = 0; // 重置总时间和计时的预约数量
            continue; // 继续下一个预约的读取
        }
        if (x == 'S') book[i][k] = time_change(h, m); // 如果预约类型为'S',记录预约的开始时间
        if (x == 'E' && book[i][k] != 0) { // 如果预约类型为'E',并且有对应的开始时间
            time += time_change(h, m) - book[i][k]; // 计算该预约所用的时间,并累加到总时间
            cnt += 1; // 增加计时的预约数量
            book[i][k] = 0; // 将该预约的开始时间设置为0,表示已经结束
        }
    }

    return 0;
}

L1-044 稳赢

题目内容:

解题思路:

本题主要难点在于让分的那局,也就是隔几局需要输一次,对于这个问题可以设定一个计数值,优先判定计数值有没有到设定值,是就输出一样的值,不是再进行判定。

C代码展示:

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

int main()
{
	int n, k=0;
	scanf("%d", &n);
	while(1){
		char temp[10];
		scanf("%s", temp);
		if (!strcmp("End", temp)) break;
		if (k == n){
			k = 0;
			printf("%s\n", temp);
		}
		else{
			k++;
			if (!strcmp("ChuiZi", temp)) printf("Bu\n");
			else if (!strcmp("JianDao", temp)) printf("ChuiZi\n");
			else printf("JianDao\n");
		}
	}
	
	return 0;
}

L1-045 宇宙无敌大招呼

题目内容:

解题思路:

略。

C代码展示:

#include <stdio.h>

int main()
{
	char s[10]={0};
	gets(s);
	printf("Hello %s\n",s);
	return 0;
}

L1-046 整除光棍

题目内容:

解题思路:

遍历 111…11 对于不同长度的值都对输入的num取余,当值为0时就是最短的满足条件的值。

但是,可以对这个代码进行升级,采用累除的方式进行判断,也就是解法二。

C代码展示:

//解法一:

#include <stdio.h>

int main() {
    int num, n = 1, i = 0, j = 0, k = 1, flag = 0;
    scanf("%d", &num);
    for (; n % num != 0; n = n * 10 + 1) // 循环直到n能被num整除
    {
        k++; // 每次循环迭代,周期计数器k增加1
        if (n / num != 0 || flag) // 如果n除以num的商非零或flag已经被设置
        {
            flag = 1; // 设置flag,表示已经开始输出
            printf("%d", n / num); // 输出n除以num的商
            i++; // 增加输出计数器i
            n = n % num; // 更新n为n除以num的余数,为下一轮计算做准备
        }
    }
    printf("%d", n / num); // 输出最后一个能被num整除的数
    i += 1; // 增加输出计数器i
    printf(" %d\n", k); // 输出循环周期的长度k

    return 0;
}
//解法二:

#include <stdio.h>

int main() {
    int n, j; // 定义变量n(除数)和j(循环变量)
    int ans[10000] = {0}; // 定义一个数组ans,用于存储计算过程中的中间结果,初始化为0

    scanf("%d", &n); // 读取除数n
    for (int i = 1; ; i++) { // 进入一个无限循环,i用于记录当前的迭代次数
        int num = 1; // 初始化num为1,num用于生成数列
        for (j = 0; j < i; j++) { // 内层循环,用于计算数列的第i项
            ans[j] = num / n; // 计算当前数除以n的商,并存储在ans数组中
            num = num % n * 10 + 1; // 更新num为下一个数,即当前数除以n的余数乘以10再加1
        }
        if (num == 1) { // 如果num等于1,说明找到了一个循环周期
            int flag = 0; // 定义一个标志变量flag,用于控制输出格式
            for (int k = 0; k < j; k++) {
                if (flag || ans[k] != 0) { // 如果flag为1或者当前数不为0,输出当前数
                    printf("%d", ans[k]); // 输出当前数
                    flag = 1; // 设置flag为1,表示已经开始输出
                }
            }
            printf(" %d\n", i); // 输出循环周期的起始部分,并跟上循环次数
            break; // 跳出循环
        }
    }

    return 0;
}

L1-047 装睡

题目内容:

解题思路:

建议创建结构体进行输入,然后对后面两个值进行判定,然后输出姓名。

C代码展示:

#include <stdio.h>

typedef struct _{
	char name[10];
	int a;
	int b;
} id;

int main()
{
	int n;
	scanf("%d", &n);
	for (int i=0; i<n; i++){
		id peo;
		scanf("%s %d %d", peo.name, &peo.a, &peo.b);
		if (peo.a < 15 || peo.a > 20 || peo.b < 50 || peo.b > 70){
			printf("%s\n", peo.name);
		}
	}
	
	return 0;
}

L1-048 矩阵A乘以B

题目内容:

解题思路:

本题主要麻烦的地方在于矩阵相乘的时候,循环的位置混乱。但是只能说自己多列一列运算关系和顺序。

C代码展示:

#include <stdio.h>

int main() {
    int ra, ca, rb, cb, A[100][100], B[100][100];
    scanf("%d %d", &ra, &ca); // 读取矩阵A的行数和列数
    for (int i = 0; i < ra; i++) { // 循环读取矩阵A的所有元素
        for (int j = 0; j < ca; j++) {
            scanf("%d", &A[i][j]);
        }
    }
    scanf("%d %d", &rb, &cb); // 读取矩阵B的行数和列数
    for (int i = 0; i < rb; i++) { // 循环读取矩阵B的所有元素
        for (int j = 0; j < cb; j++) {
            scanf("%d", &B[i][j]);
        }
    }
    if (ca == rb) { // 如果矩阵A的列数等于矩阵B的行数,可以进行矩阵乘法
        printf("%d %d\n", ra, cb); // 输出结果矩阵的行数和列数
        for (int i = 0; i < ra; i++) { // 循环计算结果矩阵的所有元素
            for (int j = 0; j < cb; j++) {
                int sum = 0; // 初始化元素和为0
                for (int k = 0; k < ca; k++) { // 计算矩阵A的第i行与矩阵B的第j列的点积
                    sum += A[i][k] * B[k][j];
                }
                if (j == 0) printf("%d", sum); // 对于每行的第一个元素,不打印空格
                else printf(" %d", sum); // 对于每行的后续元素,打印空格后打印元素
            }
            printf("\n"); // 每行结束后打印换行符
        }
    }
    else { // 如果矩阵A的列数不等于矩阵B的行数,输出错误信息
        printf("Error: %d != %d\n", ca, rb);
    }

    return 0;
}

;