「PAT乙级真题解析」Basic Level 1106 2019数列 (问题分析+完整步骤+伪代码描述+提交通过代码)
题设要求很明确, 给定一个递推数列, 并第n项是第n-4到第n-1项的和的个位数字。 要求给定正整数n之后, 输出前n项. 于是我们的重点在于如何实现递推式得到数列的新一项, 然后一直生成到指定项即可。
#算法#数据结构#c语言#pat考试#需求分析
Table of Contents
乙级的题目训练主要用来熟悉编程语言的语法和形成良好的编码习惯和编码规范。从小白开始逐步掌握用编程解决问题。
PAT (Basic Level) Practice 1106 2019数列
问题分析
题设要求很明确, 给定一个递推数列, 并第n项是第n-4到第n-1项的和的个位数字。 要求给定正整数n之后, 输出前n项. 于是我们的重点在于如何实现递推式得到数列的新一项, 然后一直生成到指定项即可。
如何生成新一项
因为我们需要用到前4项, 所以需要记录前4项。 用前4项之和生成新项后, 需要将第1项去掉, 然后将当前新项加到前4项中的末尾, 相当于一个滑动窗口。 如果编程语言自带"队列"这种数据结构, 十分好实现。 但是C语言中没有队列, 如果每次都自行移动记录的前4项, 可能会造成超时。 于是我们重新审视为什么我们要移动记录的4项值, 原因在于我们希望每一次都减去第1项, 把新项加在末尾。 但C语言难以实现我们这个直觉上想到的第一方案, 我们需要换一个方案。 其实我们需要的是知道接下来要减去哪一项(第一方案就是通过队列让我们确定每一次都减去第一项) 所以我们可以记录当前的迭代次数, 然后通过模运算, 在记录的4项值中循环进行数值更新。
样例
当前记录的前4项: 2 0 1 9 当前和: 12
生成第5项(记当前迭代次数为0)
- 当前和取个位数字, 得到新项"2"
- 当前和减去"前4项中索引为0的位置上的值", 即减去2, 等于10
- 当前和加上新项的值, 即加上2, 等于12
- 将前4项中索引为0的位置, 值更新为新项的值, 即更新为2
- 迭代次数+1
生成第6项(当前迭代次数: 1)
- 当前和取个位数字, 得到新项"2"
- 当前和减去"前4项中索引为1的位置上的值", 即减去0, 等于12
- 当前和加上新项的值, 即加上2, 等于14
- 将前4项中索引为1的位置, 值更新为新项的值, 即更新为2
- 迭代次数+1
生成第7项(当前迭代次数: 2)
- 当前和取个位数字, 得到新项"4"
- 当前和减去"前4项中索引为2的位置上的值", 即减去1, 等于13
- 当前和加上新项的值, 即加上2, 等于17
- 将前4项中索引为1的位置, 值更新为新项的值, 即更新为4
- 迭代次数+1
生成第n项(当前迭代次数: n-4)
......
完整描述步骤
- 获取输入: 正整数n
- 初始化记录器:
- 前4项 = {2, 0, 1, 9};
- 前4项和 = 12;
- 检查给定的正整数是否小于等于4:
- 如果小于等于4:
- 由于起始4项已知, 直接输出到指定项即可
- 如果大于4:
- 输出"2019"
- 从第5项到第n项, 记迭代次数起始值为0:
- 新项 = 前4项和 % 10;
- 输出新项
- 前4项和 -= 前4项[迭代次数 % 4]
- 前4项和 += 新项
- 前4项[迭代次数 % 4] = 新项
- 迭代次数+1
- 如果小于等于4:
伪代码描述
- get input: item_order;
- init recorder:
- last_four = {2, 0, 1, 9};
- last_four_sum = 12;
- if item_order <= 4:
- for order in range(0, item_order):
- print(last_four[order])
- end procedure;
- for order in range(0, item_order):
- if item_order > 4:
- print("2019");
- for order in range(4, item_order):
- new_item = last_four % 10;
- print(new_item);
- last_four_sum -= last_four[order % 4];
- last_four_sum += new_item;
- last_four[order % 4] = new_item;
完整提交代码
/*
# 问题分析
题设要求很明确, 给定一个递推数列, 并第n项是第n-4到第n-1项的和的个位数字。
要求给定正整数n之后, 输出前n项.
于是我们的重点在于如何实现递推式得到数列的新一项, 然后一直生成到指定项即可。
## 如何生成新一项
因为我们需要用到前4项, 所以需要记录前4项。
用前4项之和生成新项后, 需要将第1项去掉, 然后将当前新项加到前4项中的末尾, 相当于一个滑动窗口。
如果编程语言自带"队列"这种数据结构, 十分好实现。
但是C语言中没有队列, 如果每次都自行移动记录的前4项, 可能会造成超时。
于是我们重新审视为什么我们要移动记录的4项值, 原因在于我们希望每一次都减去第1项, 把新项加在末尾。
但C语言难以实现我们这个直觉上想到的第一方案, 我们需要换一个方案。
其实我们需要的是知道接下来要减去哪一项(第一方案就是通过队列让我们确定每一次都减去第一项)
所以我们可以记录当前的迭代次数, 然后通过模运算, 在记录的4项值中循环进行数值更新。
## 样例
当前记录的前4项: 2 0 1 9
当前和: 12
### 生成第5项(记当前迭代次数为0)
- 当前和取个位数字, 得到新项"2"
- 当前和减去"前4项中索引为0的位置上的值", 即减去2, 等于10
- 当前和加上新项的值, 即加上2, 等于12
- 将前4项中索引为0的位置, 值更新为新项的值, 即更新为2
- 迭代次数+1
### 生成第6项(当前迭代次数: 1)
- 当前和取个位数字, 得到新项"2"
- 当前和减去"前4项中索引为1的位置上的值", 即减去0, 等于12
- 当前和加上新项的值, 即加上2, 等于14
- 将前4项中索引为1的位置, 值更新为新项的值, 即更新为2
- 迭代次数+1
### 生成第7项(当前迭代次数: 2)
- 当前和取个位数字, 得到新项"4"
- 当前和减去"前4项中索引为2的位置上的值", 即减去1, 等于13
- 当前和加上新项的值, 即加上2, 等于17
- 将前4项中索引为1的位置, 值更新为新项的值, 即更新为4
- 迭代次数+1
### 生成第n项(当前迭代次数: n-4)
......
# 完整描述步骤
1. 获取输入: 正整数n
2. 初始化记录器:
- 前4项 = {2, 0, 1, 9};
- 前4项和 = 12;
3. 检查给定的正整数是否小于等于4:
- 如果小于等于4:
- 由于起始4项已知, 直接输出到指定项即可
- 如果大于4:
- 输出"2019"
- 从第5项到第n项, 记迭代次数起始值为0:
- 新项 = 前4项和 % 10;
- 输出新项
- 前4项和 -= 前4项[迭代次数 % 4]
- 前4项和 += 新项
- 前4项[迭代次数 % 4] = 新项
- 迭代次数+1
# 伪代码描述
1. get input: item_order;
2. init recorder:
- last_four = {2, 0, 1, 9};
- last_four_sum = 12;
3. if item_order <= 4:
- for order in range(0, item_order):
- print(last_four[order])
- end procedure;
4. if item_order > 4:
- print("2019");
- for order in range(4, item_order):
- new_item = last_four % 10;
- print(new_item);
- last_four_sum -= last_four[order % 4];
- last_four_sum += new_item;
- last_four[order % 4] = new_item;
*/
# include<stdio.h>
int main(){
int item_order;
scanf("%d", &item_order);
int last_four[4] = {2, 0, 1, 9};
int last_four_sum = 12;
if (item_order <= 4){
for (int i = 0; i < item_order; i++){
printf("%d", last_four[i]);
}
return 0;
}
printf("2019");
int current;
for (int i = 4; i < item_order; i++){
current = last_four_sum % 10;
printf("%d", current);
last_four_sum -= last_four[i % 4];
last_four_sum += current;
last_four[i % 4] = current;
}
return 0;
}