1751 分解因数 By Oler30
【题目重述】
总时间限制: 1000ms
内存限制: 65536kB
给出一个正整数a,要求分解成若干个正整数的乘积,即a = a1 * a2 * a3 * ... * an,并且1 < a1 <= a2 <= a3 <= ... <= an,问这样的分解的种数有多少。注意到a = a也是一种分解。
输入
第1行是测试数据的组数n,后面跟着n行输入。每组测试数据占1行,包括一个正整数a (1 < a < 32768)
输出
n行,每行输出对应一个输入。输出应是一个正整数,指明满足要求的分解的种数
样例输入
2
2
20样例输出
1
4
一、题目分析
此题不是求因数的个数,而是求一个数被分解的方法,所以求出因数的个数再用因数求分解种类很麻烦,得另辟蹊径。
可以想:4*9=36和9*4=36是一样的,可以想到利用的因数个数前一半来求题目的分解种类,即j/i>=i.否者结束,其中这个过程利用到了递归和自调用。
二、算法说明
利用for循环来控制一个数的分解方式,过程要求:1. 商大于等于除数2.如果满足第一条自调用,调用中不满足第一条规定,则退出,继续for循环。
三、数据结构
构成一个分解方式的要求是商大于等于除数,且起始除数为2,逐渐递增1。
四、代码及代码说明
#include<stdio.h>
int sum[50],k;//sum[50]表示所有数的分解种数构成的一个答案数组,k来控制每一个数的分解种数放在一个数组元素中//
void fun(int j,int a)//求一个数的分解种类的函数//
{
int i;
for(i=j;i<a;i++)
{
if(a%i==0&&i<=a/i)//保证商大于等于除数,即利用因数个数的前一半个数来确定//
{
sum[k]++;
fun(i,a/i);//调用自身函数,确实商是否还可以分解,如果可以,那么商的商也必须符合大于等于除数,否者continue//
}
if(i>a/i)//商小于除数,超过因数个数的一半,停止//
break;
}
}
int main()
{
int n,a[50],i;//,n表示个数,a[50]表示输入所有数构成一个被求数组//
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
for(i=0;i<n;i++)
{
k=i;
sum[k]=1;//表示自身的一个数也表示一个分解方法//
fun(2,a[i]);
}
for(i=0;i<n;i++)//输出所以输入数据的分解种数//
printf("%dn",sum[i]);
return 0;
}
五、算法说明
原本是想利用把一个数的所有因数都求出来,然后利用排列组合的方式来求解,发现因数之间的因数关系使得利用这一方法非常麻烦,所有就想到了,一个数存在一个因数,必定存在另一个因数,这两个因数的积就是这个数,另一方面,一个数如果存在因数,那么因数的个数必定为偶数个,所有想到了利用一个数所有因数个数的一半来求解问题,另外考虑到,数的因数是否存在因数,且是否满足商大于等于除数,这就可以完美跳过利用因数的排列组合方式求解,求时间复杂度大大降低。
(只有短短的2ms)