–
分解因数(递归,思维)
–
题目描述
给出一个正整数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);
}
}