PTA python实现 7-37 整数分解为若干项之和 (20 分)

7-37 整数分解为若干项之和 (20 分)

将一个正整数N分解成几个正整数相加,可以有多种分解方法,例如7=6+1,7=5+2,7=5+1+1,…。编程求出正整数N的所有整数分解式子。

输入格式:

每个输入包含一个测试用例,即正整数N (0<N≤30)。

输出格式:

按递增顺序输出N的所有整数分解式子。
递增顺序是指:对于两个分解序列 N1 = {n1,n2,⋯} 和 N2 = {m1,m2,⋯}
若存在 i 使得 n1 = m1 , ⋯ , ni = mi,但是 ni+1 < mi+1 ,则 N1 序列必定在 N2 序列之前输出。
每个式子由小到大相加,式子间用分号隔开,且每输出4个式子后换行。

输入样例:

7

输出样例:

7=1+1+1+1+1+1+1;7=1+1+1+1+1+2;7=1+1+1+1+3;7=1+1+1+2+2
7=1+1+1+4;7=1+1+2+3;7=1+1+5;7=1+2+2+2
7=1+2+4;7=1+3+3;7=1+6;7=2+2+3
7=2+5;7=3+4;7=7

解题思路

这个题目很显然应该用递归的想法去做,但是退出条件和递归式子还需要仔细琢磨。
先做例子分析F(5)的结构


image.png

可以看到,数字始终是呈现递增的形式,无论是上下还是左右,都是后面的数字比前面的数字更大。
而且 第1位 数除了其本身,都不会超过 F(n) 中的 n/2 ,然后就是一种n的本身的特殊情况。
如果我们把第一位数设为 i ,将从 i 开始的 F(n),记为 F(n , i )
那么 F(5) 就可以拆分成 F(5,1) , F(5,2) ,F(5,5)三种情况。


F(5) 全分解

F(5,1) 又可以看成是 1 + F(4) , F(4) 则可以看成 F(4,1) , F(4,2) , F(4,4) ...
又或者可以看成是 2 + F(3,2) , F(3,2) 可以拆分为 F(3,3) 因为 F(3,2) 的从 2 开始,而 2 > 2/3,所以舍去了,...

F(5) 拆分

F(4) 拆分

F(3,2) 拆分

根据以上观察可以发现,只有在 F(n,n)的时候,条件才会结束,并且最后的那一位数字就是 n ,而前面的那一串加法数与上一级相同。
所以我们可以把上一级的前面那一串加法数,传到本级,然后决定在末尾加上 a+ 以后传递到下级,或者是直接输出。
于是式子被改造成F(n , i , str) , n 就是需要求式子的和数,i 就是本级运算需要放在式子第一位的最小数字,str就是上一级传下来的需要被输出的字符串,即图中 1+1+F(2,2) 中的 '1+1+' ,2+F(3,2) 的 该式子写法就是 F(3,2, '2+')。

我这么写可能理解起来有些困难,我还是直接放代码吧,配合代码理解起来应该会更容易。
代码不多,主要算法代码只有十几行。

最终答案

def main():
    # 输入,起始条件
    n = int(input())
    f(n,1,str(n)+'=')

#计数换行,全局变量
count = 0

def f(n, startnum,out=''):
    global count
    # 递归,从 startnum ,到 n/2 取整 ,range()特性 +1
    # 用 out字符串 来存储前面的数字,outmp是当前式子用的,输出即弃用
    for i in range(startnum,n//2 + 1):
        outmp = out
        outmp += str(i) + '+'
        f(n-i,i,outmp)
    
    # 退出条件就是 startnum == n,把前面的 out字符串 输出,然后 n 直接输出在末尾就行
    # 判断是否换行,最后一个没有';',用是否包含 '+' 取了巧规避了
    # 由于这是最后一位数,所以也能控制 '+' 不会添加在末尾 
    if n == startnum:
        print(out + str(n),end='')
        count += 1
        if  (count % 4) ==0:
            print()
        elif '+' in out:
            print(';',end='')
        return

    # 最后当然还要输出一个前面没有加和的整数
    # if startnum < n:
    f(n,n,out)

main()

参考资料

感谢以下资料在解决该问题时提供的帮助,大家也可以参考看看。
这篇是递归方式
7-37 整数分解为若干项之和(20 分)- lingr7
这篇用了递推方式
PTA_数据结构学习与实验指导_题解_2-2.5 整数分解为若干项之和 - 满眼星辰

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 210,978评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 89,954评论 2 384
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,623评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,324评论 1 282
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,390评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,741评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,892评论 3 405
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,655评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,104评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,451评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,569评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,254评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,834评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,725评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,950评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,260评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,446评论 2 348

推荐阅读更多精彩内容