分解因数(递归,思维)

分解因数(递归,思维)

链接:OpenJudge 分解因数

题目描述

给出一个正整数a,要求分解成若干个正整数的乘积,即a = a1 * a2 * a3 * … * an,并且1 < a1 <= a2 <= a3 <= … <= an,问这样的分解的种数有多少。注意到a = a也是一种分解。

input
第1行是测试数据的组数n,后面跟着n行输入。每组测试数据占1行,包括一个正整数a (1 < a < 32768)

output
n行,每行输出对应一个输入。输出应是一个正整数,指明满足要求的分解的种数

simple input

2
2
20

simple output

1
4

思路


方案一.

构造函数js(b,aa),表示计算从b开始直到aa,所有分解总数之和。

void js(int b, int aa)
{
	if (aa == 1)
	{
		a++;
		return;
	}
	else
		for (int i = b;i <= aa;i++)
			if (aa % i == 0)
				js(i, aa / i);
}

代码分析:

定义循环变量 i,从 b 开始,若 aa 能整除i,则表明 i 是 aa 的一个因子,此时令 i 等于下一循环中的 b,令 aa / i 等于下一循环中的 aa ,递归查找 aa 的其他因数。

Note:
1)由于 i 是升序查找,因此每一次找到的因子都必然大于等于 b ,避免重复查找的情况(例如12:当 b = 2 时,查找出的分解情况为2 * 2 * 3,而当 b = 3 时,由于升序查找的原因,查找出来的情况为3 * 4,不会出现3 * 2 * 2 的重复查找)。

2)当 aa == 1 时,aa 无法再分解,代表找到一种分解方式,因此令计数器 a++ ,再回溯寻找下一种分解方式。

3)例如当 aa == 100 时,执行过程: js( 2, 100) --> js( 2, 50) --> js( 2, 25) --> js( 5, 5) --> js( 5, 1) --> a++ --> 回溯至 js( 2, 25) 继续寻找 --> …

方案一执行时间比方法二久(俺也不知道为啥

AC 代码

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

int a;

void js(int b, int aa)
{
	if (aa == 1)
	{
		a++;
		return;
	}
	else
		for (int i = b;i <= aa;i++)
			if (aa % i == 0)
				js(i, aa / i);
}

int main()
{
	int n;
	scanf("%d", &n);
	while (n--)
	{
		a = 0;
		int aa;
		scanf("%d", &aa);
		js(2, aa);
		printf("%d\n", a);
	}
}

方案二.

与方案一相似,构造函数 js(int a, int b),代表从 b 开始,所有的分解方案之和。不同点在于,这次的递归时自顶向下,从 b 开始,到 1 结束。

int js(int a, int b)
{
	if (a == 1)
		return 1;
	if (b == 1)
		return 0;
	if (a % b == 0)
		return js(a / b, b) + js(a, b - 1);
	else
		return js(a, b - 1);
}

代码分析:
若 a 能整除 b ,表明 b 是 a 的一个因子,则一除到底(原因与方案一相似),并继续寻找 a 的因子;若不能整除,表明 b 不是 a 的因子,则令 b - 1,继续寻找 a 的因子。

Note:

1)若 a == 1,说明 a 无法继续分解,代表着找到了一种分解方案,返回 1 。

2)若 b == 1,说明 a 无法继续分解,但此时应返回 0 ,因为此时的方案已经在 b == a 时就被计算(例如 a == 5 时,只有一种分解方案,此方案在 b == 5 时就已经 return 1,若在 b == 1 时再次 return 1,则会导致重复计算)。

AC代码

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<algorithm>
using namespace std;

int js(int a, int b)
{
	if (a == 1)
		return 1;
	if (b == 1)
		return 0;
	if (a % b == 0)
		return js(a / b, b) + js(a, b - 1);
	else
		return js(a, b - 1);
}

int main()
{
	int n, a;
	scanf("%d", &n);
	while (n--)
	{
		scanf("%d", &a);
		int x = js(a, a);
		printf("%d\n", x);
	}
}
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值