题目
一个正整数 N 的因子中可能存在若干连续的数字。例如 630 可以分解为 3×5×6×7,其中 5、6、7 就是 3 个连续的数字。给定任一正整数 N,要求编写程序求出最长连续因子的个数,并输出最小的连续因子序列。
输入格式:
输入在一行中给出一个正整数 N(1<N<231)。
输出格式:
首先在第 1 行输出最长连续因子的个数;然后在第 2 行中按 因子1*因子2*……*因子k
的格式输出最小的连续因子序列,其中因子按递增顺序输出,1 不算在内。
输入样例:
630
输出样例:
3
5*6*7
思路
整体的思路也就是双重for循环暴力求解,但是许多细节部分需要注意。
由于题目让求出最长的连续因子序列,是连续的,所以只需要知道这个序列的第一个数和长度就可以将整个序列表示出来,因此也就不需要用数组存了。
效率的优化:一个数 n = a * b,如果a小于根号下n,那么b就一定大于根号下n。所以找因子的外层循环小于根号下n就可以满足要求,降低了时间复杂度。i < n 优化为 i <= sqrt(n)。
素数的情况:如果是素数,length是0,如果输出0肯定是不满足题目要求的,因此要单独考虑这一情况。可以加个if,如果length为0,说明n除了1和它本身之外没有别的因子(0到根号下n的范围没有因子,那么从根号下n到n这一范围也一定没有因子),这时直接输出1和n就可以了。
代码
#include <iostream>
#include <math.h>
using namespace std;
int main(){
int n;
cin >> n;
int start;//最长连续因子序列的第一个数
int length = 0;//最长连续因子序列的长度
for (int i = 2; i < sqrt(n); i++){
long long yin = 1;//当前连续因子序列的乘积
for (int j = i; yin < n; j++){//--j优化为yin
yin *= j;
if (n % yin == 0){
if (j - i + 1 > length){
start = i;
length = j - i + 1;
}
}
else{
break;
}
}
}
if (length == 0){
cout << "1" << endl << n << endl;
return 0;
}//倒数第二个测试点
cout << length << endl;
for (int i = 0; i < length; i++){
cout << start + i;
if (i != length - 1){
cout << "*";
}
}
cout << endl;
return 0;
}
//因为是连续的,所以只用知道起始值和长度就可以了,不需要数组存
//i < n 优化为 i <= sqrt(n)
//如果是素数,length = 0,输出的结果不对,所以要把这种情况单独讨论