1043: 递归13(因式分解【深搜+剪枝 或 DP 】)
时间限制: 1 Sec 内存限制: 128 MB
题目描述
【题意】
分解一个整数n,格式如下:
n = a1a2a3a4…am
比如:
12=12
12=62
12=43
12=34
12=322
12=26
12=232
12=223
总共8种
【输入格式】
一行一个整数n(1 < n < = 2^31 )。
【输出格式】
输出分解的总数。
【样例输入】
12
【样例输出】
8
题解~~
对于一道题目完美的代码并不是凭空出现的,而是要经过一步步的探索/
第一想法都可能是暴力求解
像下面 直接枚举,搜索
然而注意到n(1 < n < = 2^31 )
n为2^31,,,
显然后面几个点过不了,但不失为一种方法,还是记录下来。
#include<cstdio>
#include<iostream>
using namespace std;
int ans;
void dfs(int n){
ans++;//1*n也是可以的所以直接ans++
for (int i=n-1;i>1;i--){
if (n%i==0){//枚举因数可以则继续分解
dfs(n/i);
}
}
}
int main(){
int n;
scanf("%d",&n);
ans=0;dfs(n);
printf("%d",ans);
return 0;
}
上述代码会超时27%做的时间。
当然不能放弃,看上述代码显然需要优化。
不如直接将因子存进一个数组来,这样会节省一些复杂度。
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
int a[11000],len;
void fz(int x){
int t=int(sqrt(double(x+1)));//与素数类似,从根号x找起(注意取整)
for (int i=2;i<=t;i++){
if (x%i==0){//如果是x因子则
a[++len]=i;
if (x/i!=i)a[++len]=x/i;//如果x整除i不是i,则存另一个因子
}
}
}
int n,ans;
void dfs(int d){//搜索时直接搜索因子
ans++;
for (int i=1;i<=len;i++){
if (n%(d*a[i])==0&&n!=d*a[i]){
dfs(d*a[i]);
}
}
}
int main(){
scanf("%d",&n);
len=0;fz(n);
ans=0;dfs(1);
printf("%d\n",ans);
return 0;
}
但是优化后还是发现超了9%
仔细观察发现还可以继续优化
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int a[11000],len;
void fz(int x){
int t=int(sqrt(double(x+1)));
for (int i=2;i<=t;i++){
if (x%i==0){
a[++len]=i;
if (x/i!=i)a[++len]=x/i;
}
}
}
int n,ans;
void dfs(int d){
ans++;
for (int i=1;i<=len;i++){
if (d*a[i]>n) break;//如果因子比n大则直接跳出
if (n%(d*a[i])==0&&n!=d*a[i]){
dfs(d*a[i]);
}
}
}
int main(){
scanf("%d",&n);
len=0;fz(n);
sort(a+1,a+len+1);//加了一步排序
ans=0;dfs(1);
printf("%d\n",ans);
return 0;
}
加了一个排序从而达到了剪枝的目的,成功AC~