解题思路:
(1)一个正整数a,分解成若干个正整数的乘积,这几个正整数最小为2,并且是依次递增的。要求共有多少种拆解方案。
(2)那么思路是,将一个整数先除以2,如果能被整除,那么已经有了第一种方案,再看商是否能被2整除,如果可以,继续除2,有了第二种方案,依次累除,当2无法再整除的时候,便尝试3是否可以整除,如果可以,按照同样的思路继续除下去
(3)在除的过程中,什么时候就不应该除下去了呢?首先,如果一直除2的话,最后的商无法再被2整除的时候,返回。还有一点,当商除以2再次得到的商如果小于2了,也不能在除了,因为得到的结果是要形成拆解方案的,最后一个因子只能大于等于前一个因子(仔细理解)
(4)结合下列对36的拆解,体会步骤3
(5)由上图,可以理解到当最右边的分支除到3的时候,最后结果为3,此时不能再除,即使3能被3整除,结果为1,但是形成的方案为36=2*2*3*3*1,很明显不符合拆解要求,同理36=2*3*6的时候也不能再除下去,因为形成的方案为36=2*3*3*2。
(6)那除到什么时候,就可以停了呢,通过上图,思考为什么不枚举到6以后的因数呢?因为9虽然是36的因数,但是因数是一对一对出现的,在4的时候就已经有39=4*9的方案,而且是因数从小到大的,9的时候已经不符合拆解要求了。
(7)很明显,每一个数都在试着去除上一个因数,如果不可行了,便会返回上一层再去试一下能不能除更大的数,符合深度优先搜索的遍历思想,所以利用深搜来实现。
#include<bits/stdc++.h>
using namespace std;
int n,x,cnt;
//start表示开始除的最小因数,num表示被分解的数字
void dfs(int start,int num)
{
if(start>num)//如果除数大于被除数了,返回
return ;
for(int i=start;i<=sqrt(num);i++)//从start开始试除,到根号num结束
{
if(num%i==0)//可行性方案:如果当前i能被num整除
{
cnt++;//方案数加1
dfs(i,num/i);//继续深搜
}
}
}
int main()
{
cin>>n;//表示求n个数的拆解方案
for(int i=1;i<=n;i++)
{
cin>>x;//表示要拆解的数
dfs(2,x);//深度优先搜索
cout<<cnt+1<<endl;//因为本身也算一种方案
cnt=0; //计数器归零
}
return 0;
}