正整数分解-第12届蓝桥杯省赛Python真题精选

发布于:2024-04-18 ⋅ 阅读:(20) ⋅ 点赞:(0)

[导读]:超平老师的Scratch蓝桥杯真题解读系列在推出之后,受到了广大老师和家长的好评,非常感谢各位的认可和厚爱。作为回馈,超平老师计划推出《Python蓝桥杯真题解析100讲》,这是解读系列的第54讲。

正整数分解,本题是2020年12月20日举办的第12届蓝桥杯青少组Python编程省赛真题,第12届一共有两场省赛,这是第一场。题目要求将输入的正整数N分解成3个各不相同的正整数,并且不包含数字2和4。

先来看看题目的要求吧。

一.题目说明

编程实现:

输入一个正整数N(10 < N < 1000),然后将N分解成3个各不相同的正整数,即3个正整数之和为N。且要求每个正整数中都不包含数字2和4,输出一共有多少种不同的分解方法。

例如:输入的正整数N为12

将12分解为3个不同的正整数,且每个正整数都不包含数字2和4为:1,3,8和1,5,6。一共有两种分解方法。

注意:数字相同顺序不同的算一种分解方法。

输入描述:

输入一个正整数N(10 < N < 1000)

输出描述:

输出一共有多少种不同的分解方法

样例输入:

12

样例输出:

2

二.思路分析

这是一道排列组合题,考查的知识点主要包括循环、条件、字符串运算和枚举算法。

针对组合问题,在Python编程中一般有如下两种解决方案

  • 枚举算法

  • 使用combinations()组合函数

先来讨论枚举算法的实现方案,为了方便理解,我们通过两个实例来演示枚举的过程。

先以数字N = 12为例,将12拆分成3个互不相同的正整数,以1开头的有4种,如下:

1, 2, 91, 3, 81, 4, 71, 5, 6

以2开头的有2种,如下:​​​​​​​

2, 3, 72, 4, 6

以3开头的有1种,如下:

3, 4, 5

再以数字N = 18为例,将18拆分成3个互不相同的正整数,以1开头的有7种,如下:​​​​​​​

1, 2, 151, 3, 141, 4, 131, 5, 121, 6, 111, 7, 101, 8, 9

以2开头的有5种,如下:​​​​​​​

2, 3, 132, 4, 122, 5, 112, 6, 102, 7, 9

以3开头的有4种,如下:​​​​​​​

3, 4, 113, 5, 103, 6, 93, 7, 8

以4开头的有2种,如下:

4, 5, 94, 6, 8

以5开头的有1种,如下:

5, 6, 7

你发现这里的规律了吗?

如果用i、j、k来表示这3个正整数,可以发现如下3条规律:

1). i < j < k,因为(5, 6, 7)和(6, 5, 7)是相同的组合,只需要考虑前者就可以了;

2). i每次都是从1开始的,到 N // 3结束,这个也比较好理解,如果i,j,k三者相等,那么 i = j = k = N // 3,基于第一条规律,i的最大值也只能是N // 3;

3). j每次都是从 i + 1开始的,到 N // 2结束,这个怎么理解呢,因为j < k,取极端情况,i = 1,j = k,那么i +  j + k = 1 + j + j = N,由此可知,j = (N - 1)// 2。

搞清楚这3条,就可以使用枚举算法,获取所有的组合,然后去掉包含数字2和4的组合。

第二种方案则是直接使用combinations()组合函数,相当于把枚举的活儿交给专业人士来干。

思路有了,接下来,我们就进入具体的编程实现环节。

三.编程实现

根据上面的思路分析,我们使用两种方案来编写程序:

  • 枚举算法

  • 组合函数

1. 枚举算法

根据前面的思路分析,我们编写代码如下:

图片

代码不多,说明3点:

1). i和j的最大取值分别是 n // 3、n //2,由于range()函数虎头蛇尾的特点,需要加1;

2). 判断数字中是否包含2和4,最简单的方法就是使用字符串的in运算符,但是需要将整数转成字符串;

3). 对于k的取值,使用循环是可以的,但是直接利用 i + j + k = n的条件,可以省略循环,只需要确保 k > j,并且不包含数字2和4即可,这样可以极大地减少程序循环的次数,提升效率。

2. 组合函数

直接使用combinations()函数,编写代码如下:

代码比较简单,强调3点:

1). 要先导入combinations()函数;

2). combinations()函数的第一个参数是可迭代对象,这里使用range()函数生成了1到n之间的整数序列,这个范围也可以缩小到(n - 2),因为i最小值是1,j最小值为2;

3). combinations()函数返回的是元组,直接使用sum()函数对元组求和,同时过滤掉包含2和4的组合。

至此,整个程序就全部完成了,你可以输入不同的数字来测试效果啦

四.总结与思考

本题代码在12行左右,涉及到的知识点包括:

  • 循环语句,尤其是嵌套循环;

  • 条件语句;

  • 字符串运算;

  • continue语句;

  • 枚举算法;

这是本次省赛的第5题,难度中等。关键点有两个,一是如何获取所有的组合,二是如何过滤掉包含数字2和4的组合。

其中,对于组合的获取,在Python编程中,常见的方案就是循环枚举和组合函数。

对于枚举算法,需要根据实际情况来确定循环的层数,同时要对程序进行优化。包括两个方面,一是减少循环的层数,二是减少每一层循环的次数,从而提高程序的效率。

对于组合函数而言,这是Python给我们的小惊喜,尤其是combinations()和permutations()函数。真的是太好用了,能有就有,该用就用,可不要辜负了Python的一番美意。

超平老师给你留一道经典的算法入门题,看看你能否解决:


给你一个整数数组nums ,判断是否存在三元组[nums[i], nums[j], nums[k]]

满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为0且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例1:

输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。

你还有什么好的想法和创意吗,也非常欢迎和超平老师分享探讨。

如果你觉得文章对你有帮助,别忘了点赞和转发,予人玫瑰,手有余香😄

需要源码的,可以移步至“超平的编程课”gzh。