2022秋 | PTA编程训练(二)

目录​​​​​​​

11.币值转换

12.猴子选大王

13.九宫格输入法

14.抓老鼠啊~亏了还是赚了

15.大炮打蚊子

16.切分表达式--写个tokenizer吧

17.Have Fun with Numbers

18.查验身份证

19.出生年

20.福倒了


11.币值转换

题目详情:

输入一个整数(位数不超过9位)代表一个人民币值(单位为元),请转换成财务要求的大写中文格式。如23108元,转换后变成“贰万叁仟壹百零捌”元。为了简化输出,用小写英文字母a-j顺序代表大写数字0-9,用S、B、Q、W、Y分别代表拾、百、仟、万、亿。于是23108元应被转换输出为“cWdQbBai”元。

 输入格式:

输入在一行中给出一个不超过9位的非负整数。

输出格式:

在一行中输出转换后的结果。注意“零”的用法必须符合中文习惯。

输入样例:

813227345

输出样例:

iYbQdBcScWhQdBeSf

 代码及解析如下;

#include <stdio.h>
int main(){
    int n;
    char *a[10]={"a","b","c","d","e","f","g","h","i","j"};//十个数字0--9
    char *b[9]={"","S","B","Q","W","S","B","Q","Y"}; //拾、百、仟、万、十万,百万,千万,亿                                                           
    int c[10];                                       //个位数无具体名称所以空出来
    int count=0;
    int pcount;     
    scanf("%d",&n);
    if(n==0)printf("a");  //单走一个0  
    while(n>0){ 
        c[count]=n%10;    //把各个位上的数存起来
        n/=10;
        count++;
    }
    while(count>0){
        count--;           //因为是从个位存入数组,所以从最高位逆序打印
        if(c[count]==0){      //遇到0时
            if(count>=4&&count<=6){  //数字超过万且不超过亿,当中间连续有0时防止不输出W
                printf("W");
            }
            pcount=count-1;    //当前数字的下一位数
            while(pcount>=0){  //当该数字不是0时,也就是0后有数字的情况
                if(c[pcount]!=0){   //虽然count为0,但是count的下一位不是0
                    printf("a");    //这种情况只输出一个0 ,举例: 1002 --一千零二--bQa2
                    count=pcount;  
                    break;
                }
                pcount--;  
            }
            if(pcount==-1){  //当0为末尾的时候
                return 0;
            }
        }
        printf("%s",a[c[count]]);
        printf("%s",b[count]);
    }
    return 0;
}

12.猴子选大王

题目详情:

一群猴子要选新猴王。新猴王的选择方法是:让N只候选猴子围成一圈,从某位置起顺序编号为1~N号。从第1号开始报数,每轮从1报到3,凡报到3的猴子即退出圈子,接着又从紧邻的下一只猴子开始同样的报数。如此不断循环,最后剩下的一只猴子就选为猴王。请问是原来第几号猴子当选猴王?

 输入格式:

输入在一行中给一个正整数N(≤1000)。

输出格式:

在一行中输出当选猴王的编号。

输入样例:

11

 输出样例:

7

代码及解析如下:

#include <stdio.h>
#define P 1000
int main(){
    int n;
    scanf("%d",&n);  //n只猴子
    int i=0,count=1;
    int c[P]={0};    //表示刚开始都能报数
    int last=n;      //记录剩余猴子的个数
    while(last>1){
        if(c[i]==0&&count%3==0){  //该猴子报数到3了
            count=1;        //重新开始计数
            c[i]=1;         //该猴子以后不用再报数了
            last-=1;        //猴子数量-1
        }
        else if(c[i]==0){
            count++;        //计数
        }
        i++;                
        i=i%n;             //当所有的猴子都报过一遍数后,剩下的猴子数量肯定大于一,
    }                      //但是要继续统计哪只猴子报了,哪只没报,所以整除n,从头开始计数。
    for(int j=0;j<n;j++){
        if(c[j]==0){        //剩下的仍能继续报数也就是没有被提出去的就是猴王
            printf("%d",j+1);
        }
    }
    return 0;
}

13.九宫格输入法

题目详情:

假设有九宫格输入法键盘布局如下:

 [ 1,.?! ] [ 2ABC ] [ 3DEF  ]
 [ 4GHI  ] [ 5JKL ] [ 6MNO  ]
 [ 7PQRS ] [ 8TUV ] [ 9WXYZ ]
           [ 0空  ]

注意:中括号[ ]仅为了表示键盘的分隔,不是输入字符。每个中括号中,位于首位的数字字符即是键盘的按键,按一下即可输入该数字字符。多次按同一个键,则输入的字符依次循环轮流,例如按两次3,则输入D;按5次7,则输入S;按6次2,则输入A。按键0的输入组合是0空格字符,即按两次0输入空格。

你需要对于给定的按键组合,给出该组合对应的文本。

 输入格式:

输入在一行中给出数个字符的按键组合(例如 999 表示按3次9),每个字符的按键组合之间用空格间隔,最后一个输入法组合之后以换行结束。输入数据至少包括一个字符的按键组合,且输入总长度不超过500个字符。

输出格式:

在一行中输出该按键组合对应的文本。

输入样例:

22 5555 22 666 00 88 888 7777 4444 666 44

 输出样例:

ALAN TURING

代码及解析如下:

#include <stdio.h>
#include <string.h>
char n[501];
int main(){
    char ch[10][10]={"0 ","1,.?!","2ABC","3DEF","4GHI","5JKL","6MNO",
                   "7PQRS","8TUV","9WXYZ"};
    char ch2[500];
    int q;
    gets(n);              //输入按键组合
    int m=strlen(n);      //输入按键组合的长度
    int i,k=0;
    for(i=0;i<m;){
        int q,p=0,count=0;
        if(n[i]>='0'&&n[i]<='9'){
            q=n[i]-'0';  //输入的是数字
            while(n[i]>='0'&&n[i]<='9'){      //跟在这个数字后面又输入了几个相同的数字
                count++;      //表示又输入了几个相同的数字,也就是按了几下相同的键
                i++;
            }
            
            p=strlen(ch[q]);     //该数字键上有p个字符
            count=count%strlen(ch[q]);     //在该数字键上按了count次,表示的是哪个字符
            if(count==0){      //正好按下该数字键上的最后一个字符
                ch2[k++]=ch[q][p-1]; 
            }
            else{  
                ch2[k++]=ch[q][count-1];
            }
        }
        else i++;
    }
    for(i=0;i<k;i++){
        printf("%c",ch2[i]);
    }
    return 0;
}

14.抓老鼠啊~亏了还是赚了

题目详情:

某地老鼠成灾,现悬赏抓老鼠,每抓到一只奖励10元,于是开始跟老鼠斗智斗勇:每天在墙角可选择以下三个操作:放置一个带有一块奶酪的捕鼠夹(T),或者放置一块奶酪(C),或者什么也不放(X)。捕鼠夹可重复利用,不计成本,奶酪每块3元。

聪明的老鼠呢?它们每天可能会派出一只老鼠到墙角,看看墙角有啥:

  • 若什么也没有(X),老鼠们就不高兴了(Unhappy),会有长达一天(也就是第二天)的不高兴期。在不高兴期间,不派出老鼠。不高兴期结束之后,派出老鼠。
  • 若有捕鼠夹(T),这只老鼠被引诱吃掉奶酪并被打死(Dead),老鼠们会有长达两天(也就是第二和第三天)的伤心期。在伤心期间,不派出老鼠。伤心期结束之后,派出老鼠。在这种情况下,抓到1只老鼠可获得奖励10元,但同时也耗费了一块奶酪。注意,如果某一天放置了捕鼠夹但老鼠没有出现,则没有耗费奶酪。
  • 若有奶酪(C),老鼠吃了奶酪会很开心(Happy!),会有长达两天(第二和第三天)的兴奋期。在兴奋期间,即使叠加了不高兴或者伤心,也必定派出老鼠。在这种情况下,没抓到老鼠,而且耗费了一块奶酪。注意,如果某一天放置了奶酪但老鼠没有出现,则奶酪可以下次再用,没有耗费。

现在给你连续几天的操作序列,且已知第一天肯定会派出老鼠,请判断老鼠每天的状态,并计算盈利。

 输入格式:

输入在一行中给出连续的由CTX组成的不超过70个字符的字符串,以$结束。字符串中每个字符表示这一天的操作( 即X:什么都不放;T:放捕鼠夹;C:放奶酪)。题目保证至少有一天的操作输入。

输出格式:

要求在第一行输出连续的字符串,与输入相对应,给出老鼠的状态:

  • ! 表示派出老鼠吃到奶酪
  • D 表示派出老鼠被打死
  • U 表示派出老鼠无所获
  • - 表示没有派出老鼠

第二行则应输出一个整数表示盈利。(如果有亏损,则是负数)

输入样例:

TXXXXC$

输出样例:

D--U-! 
4

代码及解析如下:

#include <stdio.h>
int main(){
    int i,j;
    int a=1,b=1,d=0,e=0;//a代表兴奋期,b代表伤心期
    char c[71];
    for(i=0;i<71;i++){
        e++;        //表示派出老鼠
        scanf("%c",&c[i]);
        if(c[i]=='$'){
            break;
        }
        if(a==2||b==1){   //a=2表示处于兴奋期,b=1表示伤心期结束
            if(e==3&&a==2){ //e=3表示3天的兴奋期结束
                a=1;
                e=0;
            }           
            if(c[i]=='T'){ //抓到老鼠,老鼠伤心两天
                b=-2;
                printf("D");
                d=d+7;
            }
            else if(c[i]=='X'){ //老鼠没找到东西,不高兴一天
                b=-1;
                printf("U");
            }
            else if(c[i]=='C') {//鼠兴奋两天
                 a=2;          
                 b=1;     //无伤心气
                 d-=3;
                printf("!");
                       e=1;   //表示此后2,3天都会派出老鼠
            }
        
        }
        else printf("-");//不派出老鼠
          b++;  //不高兴或伤心会被兴奋叠加,所以始终在自增,遇到捕鼠夹或没找到东西改变
    }
    printf("\n%d",d);
}

15.大炮打蚊子

题目详情:

现在,我们用大炮来打蚊子:蚊子分布在一个M×N格的二维平面上,每只蚊子占据一格。向该平面的任意位置发射炮弹,炮弹的杀伤范围如下示意:

 O
OXO
 O

其中,X为炮弹落点中心,O为紧靠中心的四个有杀伤力的格子范围。若蚊子被炮弹命中(位于X格),一击毙命,若仅被杀伤(位于O格),则损失一半的生命力。也就是说,一次命中或者两次杀伤均可消灭蚊子。现在给出蚊子的分布情况以及连续k发炮弹的落点,给出每炮消灭的蚊子数。

输入格式:

第一行为两个不超过20的正整数MN,中间空一格,表示二维平面有M行、N列。

接下来M行,每行有N0或者#字符,其中#表示所在格子有蚊子。

接下来一行,包含一个不超过400的正整数k,表示发射炮弹的数量。

最后k行,每行包括一发炮弹的整数坐标xy(0≤x<M,0≤y<N),之间用一个空格间隔。

输出格式:

对应输入的k发炮弹,输出共有k行,第i行即第i发炮弹消灭的蚊子数。

输入样例:

5 6
00#00#
000###
00#000
000000
00#000
2
1 2
1 4

 输出样例:

0
2

代码及解析如下:

#include <stdio.h>
int main(){
    char a;
    int ch1[20][20];
    int i,j;
    int m,n;
    scanf("%d %d",&m,&n);
    getchar();   //吸收缓冲区上scanf()剩下的换行符
    
    for(i=0;i<m;i++){
        for(j=0;j<n;j++){
            scanf("%c",&a);
            if(a=='#')ch1[i][j]=2;  //将有蚊子的地方设为2,代表蚊子两滴血
            else ch1[i][j]=0;
        }
        getchar();  //吸收换行符,换行
    }
    int k,count;
    scanf("%d",&k);
    int x,y;
    for(i=0;i<k;i++){
        count=0;
        scanf("%d %d",&x,&y);
        if(ch1[x][y]!=0){  //大炮正好击中蚊子
            count++;
            ch1[x][y]=0;
        }
        if(x-1>=0){   //
            if(ch1[x-1][y]!=0){  //上一行有蚊子
                ch1[x-1][y]-=1;  //蚊子扣一滴血
                if(ch1[x-1][y]==0){  //如果蚊子只剩一滴血了,就直接把蚊子打死了
                    count++;
                    ch1[x-1][y]=0;
                }
            }
        }
        if(x+1<m){  //分析同上
            if(ch1[x+1][y]!=0){
                ch1[x+1][y]-=1;
                if(ch1[x+1][y]==0){
                    count++;
                    ch1[x+1][y]=0;
                }
            }
        }
        if(y-1>=0){    //分析同上
            if(ch1[x][y-1]!=0){
                ch1[x][y-1]-=1;
                if(ch1[x][y-1]==0){
                    count++;
                    ch1[x+1][y]=0;
                }
            }
        }
        if(y+1<n){    //分析同上
            if(ch1[x][y+1]!=0){
                ch1[x][y+1]-=1;
                if(ch1[x][y+1]==0){
                    count++;
                    ch1[x][y+1]=0;
                }
            }
        }
        printf("%d\n",count);
    }
    return 0;
}

16.切分表达式--写个tokenizer吧

题目详情:

四则运算表达式由运算数(必定包含数字,可能包含正或负符号小数点)、运算符(包括+-*/)以及小括号(())组成,每个运算数、运算符和括号都是一个token(标记)。现在,对于给定的一个四则运算表达式,请把她的每个token切分出来。题目保证给定的表达式是正确的,不需要做有效性检查。

 输入格式:

在一行中给出长度不超过40个字符的表达式,其中没有空格,仅由上文中token的字符组成

输出格式:

依次输出表达式中的tokens,每个token占一行。

输入样例:

32*((2-2)+5)/(-15)

 输出样例:

32
*
(
(
2
-
2
)
+
5
)
/
(
-15
)

 代码及解析如下:

#include <stdio.h>
#include <string.h>
int main(){
    char c[42];
    int i=0,count=0;
    gets(c);    //输入表达式
    int j=strlen(c);
    for(i=0;i<j;){
        if(i==0&&(c[i]=='-'||c[i]=='+')){  //开头是负数或正数
            printf("%c",c[i]);
            i++;
        }
        else{
            if(c[i]=='-'){  
                //前一个是数字,则为减号
                if(c[i-1]>='0'&&c[i-1]<='9')printf("%c\n",c[i]);
                //否则为负号   
                else printf("%c",c[i]);  
                i++;
            }
            //遇到数字
            else if(c[i]>='0'&&c[i]<='9'){
                //表示数字,包含小数
                while(((c[i]>='0'&&c[i]<='9')||c[i]=='.')&&i<j){  
                    //下一个字符不是数或小数点
                    if((c[i+1]<'0'||c[i+1]>'9')&&c[i+1]!='.')printf("%c\n",c[i]);
                     else printf("%c",c[i]);
                    i++;
                 }     
            }
            else{   //普通的字符
                printf("%c\n",c[i]);
                i++;
            }
        }
        
   
    }
    return 0;
}

17.Have Fun with Numbers

题目详情:

Notice that the number 123456789 is a 9-digit number consisting exactly the numbers from 1 to 9, with no duplication. Double it we will obtain 246913578, which happens to be another 9-digit number consisting exactly the numbers from 1 to 9, only in a different permutation. Check to see the result if we double it again!

Now you are suppose to check if there are more numbers with this property. That is, double a given number with k digits, you are to tell if the resulting number consists of only a permutation of the digits in the original number.

 输入格式:

Each input contains one test case. Each case contains one positive integer with no more than 20 digits.

输出格式:

For each test case, first print in a line "Yes" if doubling the input number gives a number that consists of only a permutation of the digits in the original number, or "No" if not. Then in the next line, print the doubled number.

输入样例:

1234567899        

 输出样例:

Yes

2469135798

代码及解析如下:

这道题的大体意思是:给定一串数字,然后把这串数字double以下,判断新数字的位数是否和原数字相同,并且新数字每位数字出现的次数是否和原数字相同,比如:

1234567899  double -----   2469135798   新老数字位数相同,每位数字出现的次数也相同。

#include <stdio.h>
int main(){
    int num1[20],num2[20],wei=0;  //wei表示从最低位开始计数
    int digit[10]={0};
    int flag=1;
    char a;
    a=getchar();
    while(a>='0'&&a<='9'){
        num1[wei]=a-'0';  //存入每一位数字
        digit[num1[wei++]]++;  //记录每一位数字出现的次数
        a=getchar();
    }
    for(int i=wei-1;i>=0;i--){
        num2[i]=num1[i]*2;
    }
    for(int i=wei-1;i>0;i--){   //进位处理
        if(num2[i]/10!=0){  //乘2后大于10
            num2[i]=num2[i]%10;  //取个位上的数
            num2[i-1]+=1;  //向前进1
        }
        digit[num2[i]]--;  //该数字数量少一
    }
    if(num2[0]/10!=0){   //判断最高位数字是否大于10,也就是判断新数字与原数字位数是否一致
        flag=0;
    }
    else{
        digit[num2[0]]--;
        for(int j=0;j<10;j++){
            if(digit[j]!=0){  //判断新老数字的种量是否相等
                flag=0;
                break;
            }
        }
        
    }
    if(flag==0)printf("No\n");
    else printf("Yes\n");
    for(int i=0;i<wei;i++){
        printf("%d",num2[i]);
    }
}

18.查验身份证

题目详情:

一个合法的身份证号码由17位地区、日期编号和顺序编号加1位校验码组成。校验码的计算规则如下:

首先对前17位数字加权求和,权重分配为:{7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};然后将计算的和对11取模得到值Z;最后按照以下关系对应Z值与校验码M的值:

Z:0 1 2 3 4 5 6 7 8 9 10
M:1 0 X 9 8 7 6 5 4 3 2

现在给定一些身份证号码,请你验证校验码的有效性,并输出有问题的号码

 输入格式:

输入第一行给出正整数N(≤100)是输入的身份证号码的个数。随后N行,每行给出1个18位身份证号码。

输出格式:

按照输入的顺序每行输出1个有问题的身份证号码。这里并不检验前17位是否合理,只检查前17位是否全为数字且最后1位校验码计算准确。如果所有号码都正常,则输出All passed

输入样例:

4
320124198808240056
12010X198901011234
110108196711301866
37070419881216001X

 输出样例:

12010X198901011234
110108196711301866
37070419881216001X

 代码及解析如下:

//身份证数字过长,要用字符串数组一个一个的输入
#include <stdio.h>
int main(){
    int wight[17]={7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};  //前17位数字的权重
    char M[12]={'1','0','X','9','8','7','6','5','4','3','2'}; //检验码M
    char c[100][19];     
    int n,temp=1;
    scanf("%d",&n);   //输入n次
    int i,j;
    int count=0;
    for(i=0;i<n;i++){
        scanf("%s",c[i]);  //
    }
    for(i=0;i<n;i++){
        int k=1;
        int sum=0;
        for(j=0;j<17;j++){
            if(c[i][j]<='0'&&c[i][j]>='9'){  //前十七位有数字外的字符 
             k=0;
                printf("%s\n",c[i]);  //身份证无效
                break;              }
            else sum+=(c[i][j]-'0')*wight[j];  //sum前十七位数字加权求和
        }
        if(k==1){
            if(sum%11<0||sum%11>10){  //非法数字
                    printf("%s\n",c[i]);
            }
            else if(M[sum%11]!=c[i][17]){    //检验码M不等于身份证最后一位
                printf("%s\n",c[i]);
            }
            else count++;
        }
        
    }
    if(count==n){
        printf("All passed");
    }
    return 0;
}

19.出生年

题目详情:

以上是新浪微博中一奇葩贴:“我出生于1988年,直到25岁才遇到4个数字都不相同的年份。”也就是说,直到2013年才达到“4个数字都不相同”的要求。本题请你根据要求,自动填充“我出生于y年,直到x岁才遇到n个数字都不相同的年份”这句话。

 输入格式:

输入在一行中给出出生年份y和目标年份中不同数字的个数n,其中y在[1, 3000]之间,n可以是2、或3、或4。注意不足4位的年份要在前面补零,例如公元1年被认为是0001年,有2个不同的数字0和1。

输出格式:

根据输入,输出x和能达到要求的年份。数字间以1个空格分隔,行首尾不得有多余空格。年份要按4位输出。注意:所谓“n个数字都不相同”是指不同的数字正好是n个。如“2013”被视为满足“4位数字都不同”的条件,但不被视为满足2位或3位数字不同的条件。

输入样例:

1988 4

 输出样例:

25 2013

代码及解析如下:

#include <stdio.h>
int main(){
    int y,n,a[4];   //a[4]记录出生年的各位数字,y为出生年份
    scanf("%d %d",&y,&n);
    int count=0,i;
    //i<3013的由来:y最大取3000,当n为4时,3012正好满足条件,所以i最大取3012
    for(i=y;i<3013;i++){  
        count=1;  //n至少是2
        a[0]=i%10;  //个位
        a[1]=i/10%10;  //十位
        a[2]=i/100%10;  //百位
        a[3]=i/1000; //
        //四位数字均不想等
        if(a[0]!=a[1]&&a[0]!=a[2]&&a[0]!=a[3])count++;
        //有三位数字不相等
        if(a[1]!=a[2]&&a[1]!=a[3])count++;
        //有两位数字不相等
        if(a[2]!=a[3])count++;
        if(count==n)
            break;
    }
    printf("%d %04d",i-y,i);   //i-y表示过去多少年,i为现在的年分
}

20.福倒了

题目详情:

“福”字倒着贴,寓意“福到”。不论到底算不算民俗,本题且请你编写程序,把各种汉字倒过来输出。这里要处理的每个汉字是由一个 N × N 的网格组成的,网格中的元素或者为字符 @ 或者为空格。而倒过来的汉字所用的字符由裁判指定。

 输入格式:

输入在第一行中给出倒过来的汉字所用的字符、以及网格的规模 N (不超过100的正整数),其间以 1 个空格分隔;随后 N 行,每行给出 N 个字符,或者为 @ 或者为空格。

输出格式:

输出倒置的网格,如样例所示。但是,如果这个字正过来倒过去是一样的,就先输出bu yong dao le,然后再用输入指定的字符将其输出。

输入样例:

 输出样例:

代码及解析如下:

#include <stdio.h>
#define N 101
int main(){
    int n,i,j;
    char a[N][N];
    char ch;
    scanf("%c %d",&ch,&n);
    getchar();        //接受scanf()留在缓冲区上的换行符
    for(i=0;i<n;i++){
        for(j=0;j<n;j++){
            a[i][j]=getchar();
        }
        getchar();  //换行
    }
    int count=0;
    for(i=0;i<n;i++){
        for(j=0;j<n;j++){
           //比较首尾字符是否相等,也就是看看这个字正过来倒过去是否一样
           if(a[i][j]==a[n-1-i][n-1-j]){  
                count++;
            }
        }
    }
    if(count==n*n){
        printf("bu yong dao le\n");
    }
    for(i=n-1;i>=0;i--){  //将这个字的字符从后往前输出
        for(j=n-1;j>=0;j--){
            if(a[i][j]!=' '){
                a[i][j]=ch;
            }
            else {
                a[i][j]=' ';
            }
            printf("%c",a[i][j]);
        }
        printf("\n");
    }
    return 0;
    
    
}


注: 本栏目所有的题目均来自于学校程序设计课程的平时作业,如果对您有帮助的话,请点赞加关注,有任何不理解的地方也可以在评论区中留言或者私信我哦!

码文不易,还请多多支持哦~~

  • 26
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 13
    评论
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

殿下p

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值