这道题我被坑的很惨,最开始一看题,就觉得是按照从小到大的顺序找出n的所有因子,然后再找出所有因子中最长的连续子因子就好了。设dp[i]为以i结尾,它拥有多少个连续因子。运用动态转移方程:
if(ss[i] - ss[i - 1] == 1)
dp[i] = dp[i - 1] + 1;
else
dp[i] = 1;
但是我题目并没有完全弄清楚,首先n的范围过大,直接O(n)找因子要超时,必须要用O(sqrt(n))的算法;其次,输出需要是最小的连续子因子;然后我还完全没弄明白连续子因子的概念,也就是说,所有因子相乘必须能够被n整除,比如样列,5*6*7 = 210,210可以被630整除。最后还有一个bug,比如60,它的因子连续的有2,3,4,5,6,它的前面2,3,4不能组成连续因子,因为2*3*4 = 24,24不能被60整除,但是3*4*5 = 60,刚刚可以被60整除。因此它的答案为3*4*5。
最开始这些情况我没有考虑到,尤其是最后一点。后来我通过网上找代码,稍微修改一下,让它输出2到100的结果,再与我的代码的结果对比,才找出这个bug。
虽然我的代码有点丑,但还是上代码:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <stack>
#include <cmath>
#define maxn 1005
using namespace std;
int main()
{
int n;
while(cin>>n)
{
int m, dp[1000], ss[1000];
dp[0] = 1;
m = 0;
for(int i = 2; i <= sqrt(n); i++)
if(n % i == 0)
ss[m++] = i;
int ff = m;
if(ss[m - 1] * ss[m - 1] == n)
ff = m - 1;
for(int i = ff - 1; i >= 0; i--)
ss[m++] = n / ss[i];
for(int i = 1; i < m; i++)
{
if(ss[i] - ss[i - 1] == 1)
{
long long sum = 1;
int mm = 0;
for(int j = 0; j < dp[i - 1] + 1; j++) //判断连续的因子是否满足条件
{
sum *= ss[i - j];
if(sum > n)
{
sum /= ss[i - j];
break;
}
mm++; //mm记有多少个连续因子
}
if(n % sum == 0)
dp[i] = mm;
else
dp[i] = mm - 1;
}
else
{
dp[i] = 1;
}
}
int re = 0, f = 0;
for(int i = 0; i < m; i++)
{
if(re < dp[i])
{
re = dp[i];
f = i;
}
}
if(re == 0)
{
cout<<1<<endl<<n<<endl;
}
else
{
cout<<re<<endl;
if(re == 1)
cout<<ss[0]<<endl;
else
{
for(int i = f - re + 1; i < f; i++)
cout<<ss[i]<<"*";
cout<<ss[f]<<endl;
}
}
}
return 0;
}