问题描述:编写递归函数,求一个大于2的正整数n的素因子之和
输入:一个大于2的正整数n
输出:这个数的所有素因子之和
实例
输入:4,16,30
输出:2,2,10
解题思路:
(1)题目限制用递归函数求解,便要了解递归函数的要诀:递归终止条件和递归过程;
(2)递归终止条件顾名思义,满足该条件递归函数返回到调用其的主调函数(有“递”就有“归”);
搞清楚这两点后,再思考本题要递什么,归什么。显然,是要递输入的正整数(可能不完全,我的解答过程也表明只递该正整数也不行),归这个正整数的素因子之和。搞清楚这两件事之后,开始寻找递归终止条件。
由于我在求素因子用的是蛮力求法(从2往后试),所以判断递归终止条件是( n == i )。但此时有两种情况会发生,一是当前求得的素因子和之前不等,另一种情况是相等,因而要分开写返回语句,前者返回当前i的值;后者返回0。开始解答本问题时,我没有意识到这一点,导致无法得到正确的解法。
解决了递归终止条件问题后,就要写递归过程了。也分为两种情况,我是在设置了一个求和函数又撤销的反复过程中才理解清楚这个递归过程(也许现在可能还有纰漏吧)。一种是当前i值是其素因子和非素因子。当然获得一个素因子之后还要判断是否等于之前的素因子,等于则要去掉,于是我设置了一个全局变量保存了上一步求得的素因子。通过前后两个素因子的比较才解决了这个问题。
完整代码如下:
/*问题:编写递归函数,求一个大于2的正整数的质因数之和
Written by : Jimmy Tung
Date : 2020.03.10-03.13
*/
//程序功能:
// 输入:大于2的正整数n
// 输出: n < 3 输出错误
// n 合适 输出正整数n的质因数之和
// n 过大 (先不考虑此类情况,如输入一个100位的整数)
#include <stdio.h>
#include <stdlib.h>
int Recur_Prim( int, int); //递归求解质因子
int main(void)
{
int num; //存放输入的正整数
printf("请输入一个大于2的正整数:");
while( scanf("%d", &num)!= 1 || num < 3)
{
while(getchar() != '\n') //确保读取到符合条件的正整数
;
printf("输入错误,请重新输入:");
}
printf("%d的质因子之和为:%d", num, Recur_Prim( num, 2));
system("PAUSE");
return 0;
}
//递归求解质因子之和
int prim_pre = 0; //定义一个全局变量保存此前求得的质因子,目的是为了筛掉重复的素因子
int Recur_Prim(int n, int i)
{
if( i == n && i == prim_pre) return 0; //递归终止条件1
else if( i == n && i != prim_pre) return i; //递归终止条件2
//递归过程
if( i != n && n%i == 0 )
{
n = n/i;
if( prim_pre == i )
{
return Recur_Prim( n, i);
}
else
{
prim_pre = i;
return i + Recur_Prim( n, i);
}
}
else
{
return Recur_Prim( n, ++i);
}
}
我自忖资质浅薄,关于这个问题思考了大概三天时间才想清楚。与我而言,难点主要在于理解递归终止条件上面。说来有趣的很,这个问题我是在去同学家的路上想通的,当时只想着去朋友那里玩两天,但题目未得破解的郁闷仍在心头,在车上无聊,便冥想起来,左思右想居然想通了!天意啊!