[PAT Basic Level]1014、1015、1016、1017

这篇博客详细介绍了PAT基础级别中的四道编程题:1014福尔摩斯的约会,涉及日期、小时和分钟的判断;1015德才论,讨论了排序算法在解决此类问题中的应用;1016部分A+B,解释了如何按题目要求计算部分A或B;1017A除以B,实现了大整数除法的代码实现。每道题目都包含了题目分析和源代码示例。
摘要由CSDN通过智能技术生成

1014. 福尔摩斯的约会

题目分析

这道题主要难度地方在于把题目的意思理解明白。题干有些长,叙述也有些绕,需要耐心仔细。
总结起来,需要满足下面几个条件:

  • 日期判定:前两个字符串中第一对相同的大写英文字母,此外由于日期只有7天,按题目中的方法,必须满足大写字母是A~G(前7个英文字母)
  • 小时数判定: 是前两个字符串中第二对相同的数字或大写字母A~N(前13个英文大写字母)
  • 分钟数判定: 相对简单清晰,找出后两个字符串,第一次出现相同的字母的位置。但是要注意位置是从0开始计的,不要惯性地在输出时+1

明确了题目的要求后,编写代码就会容易很多。在输出时,需要注意如果小时和分钟数不是两位数要补0,这个可以直接用printf函数%02d来解决,设置宽度为2,不足时用0补充即可。

源代码

#include <stdio.h>
#include <ctype.h>

int main()
{
    char day[7][4]={"MON","TUE","WED","THU","FRI","SAT","SUN"};
    char code[4][61];  //用int 储存4组字符串
    for(int i=0;i<4;++i)  //读入字符串
        gets(code[i]);  //未遇到文件尾或换行符时继续读取
   
    int count=0;
    int dayOrder=-1,hour=-1,minute=-1;
    while(code[0][count]!='\0'&&code[1][count]!='\0'){
        if(code[0][count]==code[1][count]){
            int judge=code[1][count];
            if(dayOrder==-1&&'A'<=judge&&judge<='G') //还未发现日期,并命中大写字母A~G
                    dayOrder=judge-'A';  //减去A的ASCII码,对应日期序号
        
            else if(dayOrder>-1){
                if('0'<=judge&&judge<='9') {hour=judge-'0';break;} //若是数字
                else if('A'<=judge&&judge<='N') {hour=judge-'A'+10; break;} //若是大写字母A~N
            }
        }
        count++;
    }
    count=0;
    while(code[2][count]!='\0'&&code[3][count]!='\0'){
        if(code[2][count]==code[3][count]&&isalpha(code[2][count])){
                minute=count;  //题目要求从0开始计数
                break;
        }
        count++;
    }
   printf("%s %02d:%02d",day[dayOrder],hour,minute);
    return 0;
}

1015. 德才论

题目分析

这道题主要的挑战在于排序算法,我测试了一下,第一次自己写了个插入排序,虽然平均时间复杂度也是 O ( n l o g n ) O(nlogn) O(nlogn),但只能部分测点通过,有两个测试点会超时。后来看网上都用了< algorithm >头文件里的sort排序函数,这个排序函数用的是快速排序,复杂度最差也是 O ( n l o g n ) O(nlogn) O(nlogn),可见有些测点的数据设置还是挺苛刻的。关于这个函数的内容网上很容易搜到,就不多说了。

源代码

#include <stdio.h>
#include <algorithm>
struct candidate{
    int id;
    int moralScore;  //德分
    int intelScore; //才分
    int sum;
};

bool compare(candidate& a,candidate& b);

int main()
{
    int caseNumber,boundLow,boundHigh;  //分别记录总人数,最低分数线和最高分数线
    int count=0;  //记录达线总人数
    int num[4]={0,0,0,0};   //记录四类考生总人数
    scanf("%d %d %d",&caseNumber,&boundLow,&boundHigh);
    candidate *scoreClass[4];  //四类考生排序记录
    for(int i=0;i<4;++i)
        scoreClass[i]=new candidate[caseNumber];
    candidate *info=new candidate[caseNumber];  
    for(int i=0;i<caseNumber;++i){
        scanf("%d %d %d",&info[i].id,&info[i].moralScore,&info[i].intelScore);
        info[i].sum=info[i].moralScore+info[i].intelScore;
    }
    
    //根据分数情况分类
    for(int i=0;i<caseNumber;++i){
        if(info[i].moralScore>=boundLow&&info[i].intelScore>=boundLow){
            count++;  //过线人数+1
            if(info[i].moralScore>=boundHigh){ //德分过优取线
                if(info[i].intelScore>=boundHigh) //才分也过,德才全尽,第一类
                    scoreClass[0][num[0]++]=info[i];  //新元素进入数组
                else   //否则第二类
                    scoreClass[1][num[1]++]=info[i]; 
                
            }
            else if(info[i].intelScore<=info[i].moralScore)   //才德兼亡,但德胜才,第三类
                    scoreClass[2][num[2]++]=info[i]; 
                    
            else //其余为第四类
                scoreClass[3][num[3]++]=info[i]; 
        }
    }
    for(int i=0;i<4;++i)  //排序
        std::sort(scoreClass[i],scoreClass[i]+num[i],compare);  
    //输出
    printf("%d\n",count);
    for(int i=0;i<4;++i)
        for(int j=0;j<num[i];++j)
            printf("%d %d %d\n",scoreClass[i][j].id,scoreClass[i][j].moralScore
            ,scoreClass[i][j].intelScore);

    //释放空间
    for(int i=0;i<4;++i)
        delete []scoreClass[i];
    delete []info;
    return 0;
}

bool compare(candidate &a,candidate& b)
{
    if(a.sum!=b.sum) return a.sum>b.sum;  //总分降序排列
    if(a.moralScore!=b.moralScore) return a.moralScore>b.moralScore;  //德分降序排列
    return a.id<b.id;  //id升序排列
}

1016. 部分A+B

题目分析:

这道题相对而言比较容易,按题意按部就班编写。求 P a P_a Pa或者 P b P_b Pb的方法是,每次除以10,根据余数是否等于 D A D_A DA D B D_B DB来判断是否命中,命中之后按当前幂次情况累加求和即可。

源代码

#include <stdio.h>

int main()
{
    int a,Da,b,Db;
    scanf("%d %d %d %d",&a,&Da,&b,&Db);
    int pa=0,pb=0;
    int res;
    int plus=1;  //用来记录10^x的值
    while(a){
        res=a%10;  //余数
        if(res==Da){
            pa+=plus*Da;
            plus*=10;
        }
        a/=10; //更新a
    }
    plus=1;  //重置
    while(b){
        res=b%10;  //余数
        if(res==Db){
            pb+=plus*Db;
            plus*=10;
        }
        b/=10; //更新b
    }
    printf("%d",pa+pb);
    return 0;
}

1017. A除以B

题目分析:

乍一看可能有些复杂,位数如此大不可能用任何现有的数据类型存储,只能考虑用字符读取然后计算。

这里我采用的算法就是将手动求除法的竖式用代码实现了一下。用一个int数组来存各位数,注意要将ASCII码转换成对应的数字。
首先将余数 r e s res res置为0,从第一位(最高位)开始,每次新一轮除法的被除数等于上一次除法的余数 r e s res res乘以10加上当前位上的数字 d i g i t [ i ] digit[i] digit[i]。即:
d i v i d e n d = r e s ∗ 10 + d i g i t [ i ] dividend=res*10+digit[i] dividend=res10+digit[i]

然后进行除法,更新余数,把相应的此轮除法得到的商存入对应的数组中,以此循环,直到计算到最后一位。

在平时的手动除法中,我们一般最高位的0都省略掉了,而采用了借位,实际上的方法是完全一致的。在产生最高位除法借位的情况下,也就对应着第一位除法商是0,正常计算,存入数组即可,但在输出时要注意可能不会输出这个0。

源代码

#include <stdio.h>

int longDivide(int* dividend,int len,int divisor,int* quotient,int& quoLen);
int main()
{
    int longNum[1001];
    int divisor;
    int quotient[10000];
    int resident;
    int len=0;
    int quoLen=0;  //记录最后商的长度
    while((longNum[len]=getchar())!=' '){
        longNum[len]-='0';  //将对应的ASCII码转换成数字
        len++;
    }
    scanf("%d",&divisor);
    resident=longDivide(longNum,len,divisor,quotient,quoLen);
    if(quoLen==1&&quotient[0]==0) printf("0");  //若商长度只有1,且第一位为0,那么商就是0
    else{
        int i=0;
        if(quotient[0]==0) //若首位记录为0(最高位除法有借位)
            i=1;
        while(i<quoLen){  
            printf("%d",quotient[i]);
            i++;
        }
    }
    printf(" %d",resident);
    return 0;
}

int longDivide(int* divarr,int len,int divisor,int* quotient,int& quoLen)
{
   
    int res=0;
    quoLen=0;  //商数组的长度置为0
    int i=0;
    while(i<len){  //对每一位依次做除法
        int dividend=res*10+divarr[i];
        res=dividend%divisor;
        quotient[quoLen++]=dividend/divisor;
        i++;
    }
    return res;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值