PAT 7.6

这篇博客介绍了PAT乙级考试中涉及的三道编程题目,包括部分A+B问题、整数除法及数字黑洞的计算。博主通过示例详细解析了每道题目的解题思路,如利用字符串操作处理位数问题,自定义排序函数实现非递增和非递减排序,以及在数字黑洞问题中如何达到Kaprekar常数6174。
摘要由CSDN通过智能技术生成

PAT Day 4

致谢:本博客参考了 @柳婼 的PAT乙级题解,清晰的算法思路、简洁的代码给了我很大启发。

完成题目:1016-1020

1016. 部分A+B (15)

题目描述:

正整数A的“DA(为1位整数)部分”定义为由A中所有DA组成的新整数PA。例如:给定A = 3862767,DA= 6,则A的“6部分”PA是66,因为A中有2个6。
现给定A、DA、B、DB,请编写程序计算PA + PB。

输⼊格式:

输⼊在⼀⾏中依次给出A、DA、B、DB,中间以空格分隔,其中0 < A, B < 10^10。
输出格式:
在⼀⾏中输出PA + PB的值。

输⼊样例1:
3862767 6 13530293 3
输出样例1:
399
输⼊样例2:
3862767 1 13530293 8
输出样例2:
0

题目分析:

  1. 由前面几天的做题经验,我们明确地知道,首先需要将a,b定义为string型变量,以实现按位读取。
  2. 此题的细节考虑在于,当判断“x部分”时,我们是将整形数x与a[i]进行比较,但string类型变量a的每个元素a[i]是char型,如果需要与输入的数字比较,一定需要类型上的调整,我们在这里采用a[i]-‘0’的方式即可,此处我们也可以直接用int(a[i])-48表示。
  3. 在算法思路上,我们记录x的出现次数n,并循环n次,每次x扩大10倍,算出a的x部分对应的数值即可。

1017. A除以B (20)

题目描述:

本题要求计算A/B,其中A是不超过1000位的正整数,B是1位正整数。你需要输出商数Q和余数R,
使得A = B * Q + R成⽴。

输⼊格式:

输⼊在1⾏中依次给出A和B,中间以1空格分隔。

输出格式:

在1⾏中依次输出Q和R,中间以1空格分隔。

输⼊样例:
123456789050987654321 7
输出样例:
17636684150141093474 3

题目分析:

  1. 输出商数上,这道题的难点在于,如何记录每位生成的商数,如果我们采用数组保存,再进行每位元素*权值的方法输出,这样会增加一个for循环,提高了程序的复杂性。
  2. 由昨天的题目中,凡是需要按位判断并按位输出的数据,我么可以将输出写在循环内部,这样会大大提高代码的简洁性。
  3. 在计算余数时,我们的方法是,每次用第一位除以除数,
  • 单独提出来第0位,便于循环语句的一致性。
  • 如果得到的商不是零,则输出(代表此为的数码)。
  • 如果得到的商是零,则*10+下一位,再计算下一位的余数(模拟了手动出发的计算过程)。
  1. 在代码实现上,我们需要注意的是,将输入写入循环体内部按位输出数码,可以减少 计算整个大数的循环语句,示例代码如下:
string s;
 int a, t = 0, r = 0;
 cin >> s >> a;

 int len = s.length();
 t = (s[0] - '0') / a;
 if ((t != 0 && len > 1) || len == 1)
 cout << t;

 r = (s[0] - '0') % a; //单独考虑第0位,将其他位写入循环

 for (int i = 1; i < len; i++) {
 t = (r * 10 + s[i] - '0') / a;
 cout << t;
 r = (r * 10 + s[i] - '0') % a;
 }
 cout << " " << temp;

1019. 数字⿊洞 (20)

题目描述:

给定任⼀个各位数字不完全相同的4位正整数,如果我们先把4个数字按⾮递增排序,

再按⾮递减排序,然后⽤第1个数字减第2个数字,将得到⼀个新的数字。⼀直重复
这样做,我们很快会停在有“数字⿊洞”之称的6174,这个神奇的数字也叫Kaprekar常数。
例如,我们从6767开始,将得到

7766 – 6677 = 1089

9810 – 0189 = 9621

9621 – 1269 = 8352

8532 – 2358 = 6174

7641 – 1467 = 6174

… …

现给定任意4位正整数,请编写程序演示到达⿊洞的过程。

输⼊格式:

输⼊给出⼀个(0, 10000)区间内的正整数N。

输出格式:

如果N的4位数字全相等,则在⼀⾏内输出“N – N = 0000”;否则将计算的每⼀步在⼀⾏内输出,直到6174作为差出现,输出格式⻅样例。注意每个数字按4位数格式输出。

输⼊样例1:
6767
输出样例1:
77666677 = 1089
98100189 = 9621
96211269 = 8352
85322358 = 6174
输⼊样例2:
2222
输出样例2:
22222222 = 0000

题目分析:

  1. 本题的第一个难点在于“非递减”与“非递增”的表示,

    这个问题在之前的题目中也遇到过,由于sort()函数默认是升序排列,所以我们需要自定义cmp函数作为sort函数的参数,返回降序排列的数字。
  2. 本题的第二个难点在于,当数字小于4位的时候需要补零,我们可以充分利用string类型变量的方法,采用insert()函数插入‘0’即可。
  3. 本题的第三个难点在于,我们所有的操作都是对string类变量的操作,如何进行int整型计算?我们可以采用 stio() 函数来实现string向int的转换。
  4. 在代码实现上,我们需要考虑2个细节,即当s等于6174和s等于0000的时候,循环结束。示例代码如下:
bool cmp(char a, char b) {return a > b;}
int main() {
 string s;
 cin >> s;
 s.insert(0, 4 - s.length(), '0');
 do {
 string a = s, b = s;
 sort(a.begin(), a.end(), cmp); //非递减序列
 sort(b.begin(), b.end()); //非递增序列
 int result = stoi(a) - stoi(b);
 s = to_string(result); //两次类型转换
 s.insert(0, 4 - s.length(), '0'); //如果位数不够,则补0
 cout << a << " - " << b << " = " << s << endl;
 } while (s != "6174" && s != "0000"); // 注意循环条件。
 return 0; }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值