L1-006 连续因子 (20 分)
一个正整数 N 的因子中可能存在若干连续的数字。例如 630 可以分解为 3×5×6×7,其中 5、6、7 就是 3 个连续的数字。给定任一正整数 N,要求编写程序求出最长连续因子的个数,并输出最小的连续因子序列。
输入格式:
输入在一行中给出一个正整数 N(1<N<2
31
)。
输出格式:
首先在第 1 行输出最长连续因子的个数;然后在第 2 行中按 因子1因子2……*因子k 的格式输出最小的连续因子序列,其中因子按递增顺序输出,1 不算在内。
输入样例:
630
输出样例:
3
567
【思路】
一开始,觉得这种拆分因子的题应该纯递归可以解决,但后来发现,由于一个整数可以有多种拆分,并且看到题目中说,按最小的连续因子序列输出,所以我转变了思路,用回溯法求解。
回溯部分好理解,就是穷举每一个可能的数作为因子,如果val == 1了,那么说明到达边界,此时就要看看这时的因子序列中,连续因子的数目是多少,如果比之前存的最大值大,那么就要修改!这里我用了一点dp的思维求最大连续因子个数
代码(最后一个测试点愣是超时,没过,去除掉所有素数,还是超时,反正大概思路是这样):
/*
思想:dfs算了
*/
#include<iostream>
using namespace std;
const int maxn = 60;
int x[maxn];
int l = 1;
int dp[maxn];
int res[maxn];
int mi = 0;
int ans = 0;
bool IsPrime(int x)
{
for(int i = 2;i * i <= x;i++)
{
if(x % i == 0)
return false;
}
return true;
}
void dfs(int val) //val表示当前的值, len表示当前连续因子的长度
{
if(val == 1)
{
//找到连续因子,用dp
dp[1] = 1;
for(int i = 2;i < l;i++)
{
if(x[i] - x[i - 1] != 1)
dp[i] = 1;
else
dp[i] = dp[i - 1] + 1;
}
int max_res = dp[1];
int max_i = 1;
for(int i = 2;i < l;i++)
{
if(max_res < dp[i]) //这里之前出了一点bug
{
max_res = dp[i];
max_i = i;
}
}
if(max_res > ans)
{
ans = max_res;
mi = max_i;
for(int i = mi - ans + 1, j = 1;i < l;i++, j++)
{
res[j] = x[i];
}
}
return ;
}
//枚举所有可能的因子
for(int i = 2;i <= val;i++)
{
if(val % i == 0)
{
x[l++] = i;
dfs(val / i);
l--;
}
}
}
int main()
{
int n;
cin >> n;
if(IsPrime(n)) //将所有质数都剪枝了,提速
{
cout << 1 << endl;
cout << n << endl;
}
else
{
dfs(n);
cout << ans << endl;
for(int j = 1;j <= ans;j++)
{
if(j != ans)
cout << res[j] << "*";
else
cout << res[j];
}
cout << endl;
}
return 0;
}
【运行结果】