[PAT Basic Level] 1036~1040

经历了1035惨痛的折磨,终于迎来一段比较轻松的编程问题,所以今天一次性刷的多些,撸了9道,把昨天落下的补回来。

1036. 和奥巴马一起编程

题目分析:

按照题目条件输出就好,主要需要考虑的就是四舍五入对边长求解一下,以及中间那些需要空格的部分。
空格建议采用printf函数带*的格式来解决,具体形式是:
printf("%*d",width,number),星号的内容会由整形变量number前的那个变量width的值来提供,当然也可以起其他名字。这个width实际上就使得程序在运行时再去确定输出的宽度。

源代码

#include <stdio.h>

int main()
{
    int len;
    char symbol;
    scanf("%d %c",&len,&symbol);
    int row=(len+1)>>1;  //四舍五入取整
    int width=len-1;
    for(int i=0;i<row;++i){
        if(i==0||i==row-1){
            for(int j=0;j<len;++j)
                printf("%c",symbol);
            printf("\n");
        }
        else printf("%-*c%c\n",width,symbol,symbol);
    }
    return 0;
}

1037. 在霍格沃茨找零钱

题目分析

这道题,求解时,不要真的按借位进位去计算零钱的各位值,可以直接把现金与应付相减,然后把各位都转化成纳特,以纳特为单位计算出被找的零钱,然后再按转换单位求模计算出加隆和西可数即可。另外负数求解时稍微注意一下,加隆求完就取绝对值,别再后面又添了负号。

源代码

#include <stdio.h>
#include <stdlib.h>
const int G2S=17;  //加隆转西可
const int S2K=29;  //西可转纳特
int main()
{
    int galleon[2],sickle[2],knut[2];
    for(int i=0;i<2;++i){
        scanf("%d",&galleon[i]); getchar();
        scanf("%d",&sickle[i]); getchar();
        scanf("%d",&knut[i]);
    }
    int change[3],sum;
    change[0]=galleon[1]-galleon[0];
    change[1]=sickle[1]-sickle[0];
    change[2]=knut[1]-knut[0];
    sum=change[0]*G2S*S2K+change[1]*S2K+change[2];
    change[0]=sum/(G2S*S2K);
    sum=abs(sum)%(G2S*S2K);
    change[1]=sum/S2K;
    sum=sum%S2K;
    printf("%d.%d.%d",change[0],change[1],sum);
    return 0;
}

1038. 统计同成绩学生

题目分析:

这题借鉴了桶排序的思想,因为分数是0~100,故开一个101的int数组,先初始化为0,然后每次把数组下标为所读取的数对应的值+1。例如读到75,就执行score[75]++;这样就方便地统计了各个成绩的人数,之后查询对应分数的人数也很方便。

源代码

#include <stdio.h>

int main()
{
    int stuNumber;
    scanf("%d",&stuNumber);
    int score[101];  //0~100 共101种成绩
    int grades;
    for(int i=0;i<101;++i)  score[i]=0; //初始化
    for(int i=0;i<stuNumber;++i){
        scanf("%d",&grades);
        score[grades]++;
    }
    int qury;
    int first=0;
    scanf("%d",&qury);
    for(int i=0;i<qury;++i){
        scanf("%d",&grades);
        if(first) printf(" ");
        printf("%d",score[grades]);
        first++;
    }
    return 0;
}

1039. 到底买不买

题目分析:

和1038一样的思想,以读取的数对应的值作为数组下标来快速完成对个数进行统计以及查询操作。先遍历一遍表示商店出售珠子的字符串,每次把读到的数相应位置的值+1;再把下面的字符串遍历一遍,这次把读到的数位置的数值-1;最后把这个数组遍历一遍就能知道珠子够不够,剩多少了。

源代码

#include<iostream>
#include <cstring>
#include <string>

int main()
{
    using namespace  std;
    int color[128];
    for(int i=0;i<128;++i) color[i]=0;
    string sell,want;
    getline(cin,sell);
    getline(cin,want);
    int len1=sell.size();
    int len2=want.size();
    for(int i=0;i<len1;++i)
        color[sell[i]]++;
    for(int i=0;i<len2;++i)
        color[want[i]]--;
    int left=0,lack=0;
    for(int i=0;i<128;++i){
        if(color[i]<0) lack-=color[i];
        else left+=color[i];
    }
    if(lack==0) printf("Yes %d",left);
    else printf("No %d",lack);
    return 0;
}

1040. 有几个PAT

题目分析:

刚刷完几道水题就来了道稍微复杂的了。不过明确了计算的思路之后,实现起来不是很麻烦。

计算思路:

首先,我们要明确怎么计算PAT的对数。给定一个P之后,对于一个A,显然这个A之后所有的T都能够构成PAT,那么这个P和这个A能产生的PAT个数就等于A后面T的个数。所以我们采取从后往前回溯的方法,每当遇到A就记录下当前位置的A后面T的个数,当遇到P就可以根据这个P后面的A的个数以及我们之前记录好的各个A后面T的个数来求出这个P能产生的PAT个数,依次回溯到头,就确定了PAT的总数。

当然,不可能每次遇到P都回去重复看一遍前面A的情况,但事实上我们也不需要回去看,因为当前的P一定可以与所有和上一个P构成PAT的那些字母构成PAT,因此当前P能构成的PAT对数等于上一个P能构成的PAT对数,以及当前P与上一个P之间遇到新遇到的A所能产生的新PAT组合数,这两者之和。

源代码

#include <iostream>
#include <string>

const long long LIMIT=1000000007;
int main()
{
    using namespace std;
    string text;
    getline(cin,text);
    int len=text.size();
    int *tNumber=new int[len]; //储存各位的A之后有多少T
    int *positP=new int[len]; //记录有效的P的位置
    int countP=0,countT=0;  //记录有效P的个数和当前A之后T的个数
    for(int i=0;i<len;++i) tNumber[i]=0;
    int i=len-1; 
    while(i>1&&text[i]!='T') i--;  //i=1时还未搜到则不必继续,有效对为0
    if(i>1) countT++; //找有效T,个数+1
    while(--i>0&&text[i]!='A')   //i=0的情况不必考虑进去,因为此时的A不会构成PAT
        if(text[i]=='T') countT++;
    int start=i;  //倒数第一个有效A,也是之后开始搜索PAT对数的起点
    tNumber[i]=countT; //记录从后往前数第一个有效的A,它后面有多少T
    while(--i>-1){
        switch(text[i]){
            case 'P': positP[countP++]=i; break; //记录此P的位置
            case 'A': tNumber[i]=countT; break; //记录该位置上A后面T的个数
            default: countT++; break;  //否则遇到T
        }
    }
    
    long long pair=0,sum=0,pre=0; //分别记录当前P构成的PAT对数,总共可构成PAT对数以及当前P前一个P构成的PAT对数
    for(i=0;i<countP;++i){
        while(start>positP[i]){  //从当前最后没统计的有效A开始,直到遇到一个P
            pair+=tNumber[start];
            start--;
        }
        sum+=pre+pair;  //因为上一个P所能构成的所有PAT对,将P替换为当前P均可构成新的
        pre+=pair;
        pair=0;
    }
    sum=sum%LIMIT;
    printf("%lld",sum);
    delete []tNumber;
    delete []positP;
    return 0;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值