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
题目分析:
- 由前面几天的做题经验,我们明确地知道,首先需要将a,b定义为string型变量,以实现按位读取。
- 此题的细节考虑在于,当判断“x部分”时,我们是将整形数x与a[i]进行比较,但string类型变量a的每个元素a[i]是char型,如果需要与输入的数字比较,一定需要类型上的调整,我们在这里采用a[i]-‘0’的方式即可,此处我们也可以直接用int(a[i])-48表示。
- 在算法思路上,我们记录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
题目分析:
- 输出商数上,这道题的难点在于,如何记录每位生成的商数,如果我们采用数组保存,再进行每位元素*权值的方法输出,这样会增加一个for循环,提高了程序的复杂性。
- 由昨天的题目中,凡是需要按位判断并按位输出的数据,我么可以将输出写在循环内部,这样会大大提高代码的简洁性。
- 在计算余数时,我们的方法是,每次用第一位除以除数,
- 单独提出来第0位,便于循环语句的一致性。
- 如果得到的商不是零,则输出(代表此为的数码)。
- 如果得到的商是零,则*10+下一位,再计算下一位的余数(模拟了手动出发的计算过程)。
- 在代码实现上,我们需要注意的是,将输入写入循环体内部按位输出数码,可以减少 计算整个大数的循环语句,示例代码如下:
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:
7766 – 6677 = 1089
9810 – 0189 = 9621
9621 – 1269 = 8352
8532 – 2358 = 6174
输⼊样例2:
2222
输出样例2:
2222 – 2222 = 0000
题目分析:
- 本题的第一个难点在于“非递减”与“非递增”的表示,
这个问题在之前的题目中也遇到过,由于sort()函数默认是升序排列,所以我们需要自定义cmp函数作为sort函数的参数,返回降序排列的数字。 - 本题的第二个难点在于,当数字小于4位的时候需要补零,我们可以充分利用string类型变量的方法,采用insert()函数插入‘0’即可。
- 本题的第三个难点在于,我们所有的操作都是对string类变量的操作,如何进行int整型计算?我们可以采用 stio() 函数来实现string向int的转换。
- 在代码实现上,我们需要考虑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; }