dfs,对超时的优化。给出一个正整数aa,要求分解成若干个正整数的乘积,即a=a1×a2×a3×...×an,并且1<a1≤a2≤a3≤...≤an,问这样的分解的种数有多少。注意到a=a也是一种分解

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

输入

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

输出

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

样例

输入数据 1

2
2
20

Copy

输出数据 1

1
4

 要知道所有的可行方案,可以先把所有的方案列出来。

先确定递归条件,显然当所有的因子相乘等于n时,计数器加1;

很容易想到的第一个优化是sum>n时return

void dfs(int n,int k,int sum){//n是输入值,k是防止重复算的,如(2,2,5),(2,5,2),属于重复,后面的会讲
   if(sum==n){
   	cnt++;
   	return;
   }
   if(sum>n)
   return;}
   

接下来就是枚举了。

for(int i=k;i<=n;i++){//k会使后面的元素必大于等于前面的元素,所以防止重复计算
       
   
        dfs(n,i,sum*i);
    }
    return;

到这里,已经可以算出n是小值了,但是n大了之后必超时。

第二个可以减时间复杂度的是,当i是n的因子时才进行递归。

for(int i=k;i<=n;i++){//k会使后面的元素必大于等于前面的元素,所以防止重复计算
       
   
        if(n%i==0){
        dfs(n,i,sum*i);}
    }
    return;

但是还是超了一个点,仔细想想,其实当sum>n的时候可以返回到上一个因子,如出现n=20,枚举的第一个结果是(2,2,2,2,2),这个时候已经超出n的值了,但是还会接着枚举(2,2,2,2,3),(2,2,2,2,4);注意之前的(if(sum>n),return)是回到调用他的地方,也就是会回到for循环,所以无法避免这种情况,因此想要避免这种没有意义的枚举,可以在for循环里面写

最后一个优化


    for(int i=k;i<=n;i++){
        if(sum*i>n)
        return ;
        if(n%i==0){
        dfs(n,i,sum*i);}
    }
    return;

全部代码

#include <bits/stdc++.h>
using namespace std;
int cnt=0,sum;
void dfs(int n,int k,int sum){
   if(sum==n){
   	cnt++;
   	return;
   }
   if(sum>n)
   return;
   
    for(int i=k;i<=n;i++){
        if(sum*i>n)
        return ;
        if(n%i==0){
        dfs(n,i,sum*i);}
    }
    return;
}
int main(){
    int n,t;
    cin>>t;
    while(t--){
    	cnt=0;
    cin>>n;
    dfs(n,2,1);//k从2开始
    cout<<cnt<<endl;}
}

本人新手,如有错误,欢迎大佬指出。

  • 16
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值