PAT乙组(1001,1002,1003)超详细解析(C语言实现,必看)

1001 害死人不偿命的(3n+1)猜想

卡拉兹(Callatz)猜想

对任何一个正整数 n,如果它是偶数,那么把它砍掉一半;如果它是奇数,那么把 (3n+1) 砍掉一半。这样一直反复砍下去,最后一定在某一步得到n=1。卡拉兹在 1950年的世界数学家大会上公布了这个猜想,传说当时耶鲁大学师生齐动员,拼命想证明这个貌似很傻很天真的命题,结果闹得学生们无心学业,一心只证(3n+1),以至于有人说这是一个阴谋,卡拉兹是在蓄意延缓美国数学界教学与科研的进展……我们今天的题目不是证明卡拉兹猜想,而是对给定的任一不超过 1000 的正整数 n,简单地数一下,需要多少步(砍几下)才能得到 n=1?

  • 输入格式:

每个测试输入包含 1 个测试用例,即给出正整数 n 的值。

  • 输出格式:

输出从 n 计算到 1 需要的步数。

  • 输入样例:
3
  • 输出样例:
5

代码长度限制 16 KB
时间限制 400 ms
内存限制 64 MB
栈限制 8192 KB

  • 解析

没什么难点就是简单的按步骤来写判断语句

  • 代码如下
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
int main(){
	
	int n;
	scanf("%d",&n);
	int count = 0;
	
	while(n!=1){
		if(n%2==0){
			n/=2;
		}else{
			n=(3*n+1)/2;
		}
		count++;//用来统计计算的次数 
	}
	printf("%d",count);
	return 0;
}

1002 写出这个数

读入一个正整数 n,计算其各位数字之和,用汉语拼音写出和的每一位数字。

  • 输入格式:

每个测试输入包含 1 个测试用例,即给出自然数 n 的值。这里保证 n 小于 10 的100次方

  • 输出格式:

在一行内输出 n 的各位数字之和的每一位,拼音数字间有 1 空格,但一行中最后一个拼音数字后没有空格。

  • 输入样例:
1234567890987654321123456789
  • 输出样例:
yi san wu

代码长度限制 16 KB
时间限制 400 ms
内存限制 64 MB
栈限制 8192 KB

  • 解析

  • 首先要计算出来输入的数字的每位之和,利用字符数组来实现

char input[1000];
    int sum = 0;
    // 读取输入
    scanf("%s", input);

    // 计算各位数字之和
    for (int i = 0; input[i] != '\0'; i++) {
        sum += input[i] - '0';
    }
	//input[i] != '\0':这是循环继续的条件。在 C 语言中,字符串以空字符 '\0' 作为结束标志,所以只要当前索引 i 对应的字符不是空字符,循环就会继续执行。
	//input[i] - '0':通过将当前字符减去字符 '0',可以将字符转换为对应的整数。比如,如果 input[i] 是 '3',其 ASCII 码值为 51,'0' 的 ASCII 码值为 48,那么 '3' - '0' 就等于 3。
    // 输出各位数字之和的拼音
  • 然后是实现用汉字来代表0-9的数字
const char *pinyin[] = {"ling", "yi", "er", "san", "si", "wu", "liu", "qi", "ba", "jiu"};

  • 最后是要实现从首位开始实现数字与对应汉字的一一对应,先进后出我们想到用栈来实现即递归
void printDigitPinyin(int num) {
    if (num / 10 > 0) {
        printDigitPinyin(num / 10);
        printf(" ");
    }
    printf("%s", pinyin[num % 10]);
}

完整代码如下

#include <stdio.h>

// 定义数字对应的拼音数组
const char *pinyin[] = {"ling", "yi", "er", "san", "si", "wu", "liu", "qi", "ba", "jiu"};

// 递归输出数字各位的拼音
void printDigitPinyin(int num) {
    if (num / 10 > 0) {
        printDigitPinyin(num / 10);
        printf(" ");
    }
    printf("%s", pinyin[num % 10]);
}

//代码执行流程
//假设 num 的值为 123,代码的执行流程如下:
//初始调用 printDigitPinyin(123),由于 123 / 10 = 12 > 0,会递归调用 printDigitPinyin(12)。
//在 printDigitPinyin(12) 中,因为 12 / 10 = 1 > 0,会递归调用 printDigitPinyin(1)。
//在 printDigitPinyin(1) 中,1 / 10 = 0,不满足递归条件,直接输出 pinyin[1 % 10],即 "yi"。
//回到 printDigitPinyin(12),在递归调用返回后,输出一个空格,然后输出 pinyin[12 % 10],即 "er"。
//回到 printDigitPinyin(123),在递归调用返回后,输出一个空格,然后输出 pinyin[123 % 10],即 "san"。
//最终输出结果为 "yi er san"。

int main() {
    char input[1000];
    int sum = 0;
    // 读取输入
    scanf("%s", input);

    // 计算各位数字之和
    for (int i = 0; input[i] != '\0'; i++) {
        sum += input[i] - '0';
    }
	//input[i] != '\0':这是循环继续的条件。在 C 语言中,字符串以空字符 '\0' 作为结束标志,所以只要当前索引 i 对应的字符不是空字符,循环就会继续执行。
	//input[i] - '0':通过将当前字符减去字符 '0',可以将字符转换为对应的整数。比如,如果 input[i] 是 '3',其 ASCII 码值为 51,'0' 的 ASCII 码值为 48,那么 '3' - '0' 就等于 3。
    // 输出各位数字之和的拼音
    printDigitPinyin(sum);
    printf("\n");

    return 0;
}

1003 我要通过!

“答案正确”是自动判题系统给出的最令人欢喜的回复。本题属于 PAT 的“答案正确”大派送 ——只要读入的字符串满足下列条件,系统就输出“答案正确”,否则输出“答案错误”。

得到“答案正确”的条件是

字符串中必须仅有 P、 A、 T这三种字符,不可以包含其它字符; 任意形如 xPATx 的字符串都可以获得“答案正确”,其中 x或者是空字符串,或者是仅由字母 A 组成的字符串; 如果 aPbTc 是正确的,那么 aPbATca 也是正确的,其中 a、 b、 c均或者是空字符串,或者是仅由字母 A 组成的字符串。 现在就请你为 PAT 写一个自动裁判程序,判定哪些字符串是可以获得“答案正确”的。

  • 输入格式:

每个测试输入包含 1 个测试用例。第 1 行给出一个正整数 n (≤10),是需要检测的字符串个数。接下来每个字符串占一行,字符串长度不超过100,且不包含空格。

  • 输出格式:

每个字符串的检测结果占一行,如果该字符串可以获得“答案正确”,则输出 YES,否则输出 NO。

  • 输入样例:
10
PAT
PAAT
AAPATAA
AAPAATAAAA
xPATx
PT
Whatever
APAAATAA
APT
APATTAA
  • 输出样例:
YES
YES
YES
YES
NO
NO
NO
NO
NO
NO

代码长度限制 16 KB
时间限制 400 ms
内存限制 64 MB
栈限制 8192 KB

  • 解析

这个题目在分析层面需要费点功夫

首先要读懂题目的要求

1. 判断字符串中是否仅有 ‘P’,‘A’, 'T’这三种字符,包含其他字符就错误
这个条件实现

这个条件实现比较简单,不赘述

2. 任意形如 xPATx 的字符串都可以获得“答案正确”,其中 x 或者是空字符串,或者是仅由字符’A’组成的字符串;

这里的意思是中间有一个A两边有对等的A或者空格都可以
那么形如

PAT
APATA
AAPATAA
AAAPATAAA

都是满足条件的
下面主要是条件三很难理解

3. 如果 aPbTc 是正确的,那么 aPbATca 也是正确的,其中 a、 b、 c 均或者是空字符串,或者是仅由字母 A 组成的字符串。

看到这个条件的话其实不知道在说什么
用示例中的正确来分析以下

(aPbTc)PAT是正确的,此时a=" ",b="A",c=" " 那么把abc代入(aPbATca)中说明PAAT是正确的,以此类推,若b = "AAAA......",ac不变还是空格,那么PAAA.....T 依然是正确的
再举一个例子
(aPbTc)AAPATAA对应a="AA",b="A",c="AA"是正确的,那么代入到(aPbATca)中,说明了对应AAPAATAAAA是正确的,类推一下,我们发现,如果满足了
P之前的A的个数*P之后和T之前的个数=T之后的个数,那么这个就是我们解题的关键

综上所述我们只需要满足三个最关键的东西

  1. 不能包含出PAT三个字母以外的字母
  2. 开头的’A’的个数 )乘以 (中间的’A’的个数) 等于(结尾的’A’的个数)
    注意
    如果开头和结尾为0个那么只要中间的个数不为0都成立,也满足上述的式子

完整代码如下

#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
int judge(char *s) {
	
	for(int j=0; s[j]!='\0'; j++) {
			if(s[j]!='P'&&s[j]!='A'&&s[j]!='T') {
				return 0; 
			}
		}

	int P = -1,T=-1;//这两个用来标记P和T 的位置
	int len = strlen(s);//计算字符数组的长度

	//先找到P和T 的位置

	for(int i=0; i<len; i++) {
		if(s[i]=='P') {
			if(P!=-1) {
				return 0;//说明出现了第二或者多个P,不满足情况
			}
			P = i;
		} else if(s[i]=='T') {
			if(T!=-1) {
				return 0;
			}
			T=i;
		}
	}

	if(P==-1||T==-1||P>=T-1) {
		return 0; // 没有 'P' 或 'T',或者 'P' 在 'T' 之后,或者 'P' 和 'T' 相邻
	}
	int a = P;//开头的A的个数,注意不要-1,如果索引为4说明前面有0,1,2,3四个A 
	int b = T-P-1;//中间的A的个数 
	int c = len-T-1;//结尾的A的个数 
	
	
	return a*b==c;


}



int main() {
	int n;
	scanf("%d",&n);
	getchar();
	char s[101];
	for(int i=0; i<n; i++) {
		fgets(s, sizeof(s), stdin);
		// 去除 fgets 可能读取的换行符
		s[strcspn(s, "\n")] = 0;
		//
		
		if(judge(s)){
			printf("YES\n");
		} else{
			printf("NO\n");
		}
	}



	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值