一、题目
一个正整数 N 的因子中可能存在若干连续的数字。
例如 630 可以分解为 3×5×6×7,其中 5、6、7 就是 3 个连续的数字。给定任一正整数 N,要求编写程序求出最长连续因子的个数,并输出最小的连续因子序列。
输入格式:
输入在一行中给出一个正整数 N( 1 < N <231)。
输出格式:
首先在第 1 行输出最长连续因子的个数;
然后在第 2 行中按 因子1 * 因子2 * …… * 因子k 的格式输出最小的连续因子序列,其中因子按递增顺序输出,1 不算在内。
输入样例:
630
输出样例:
3
567
二、方法1
1、思路
(1)易错点分析
- 题目要求 N( 1 < N <231),所以数据类型为 long long int。
- 注意这里求的是连续因子,很多人的想法就是:我把这个数的所有因子都求解出来,然后放进一个数组里,只需要判断是不是连续即可,这样有一个很严重的问题,例如
当 N = 1680 时,其因子为 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 15, 16, 20,
21, 24, 28, 30, 35, 40, 42, 48, 56, 60, 70, 80, 84, 105, 112, 120,
140, 168, 210, 240, 280, 336, 420, 560, 840, 1680
通过这组数据,我们不难发现,貌似连续因子为 2, 3, 4, 5, 6, 7, 8,但实际上我们会发现 2 * 3 * 4 * 5 * 6 * 7 * 8 = 40320 >1680,超过 1680 了。
实际上 1680 = 2 * 3 * 4 * 5 * 7 * 2,它的连续因子仅为 2, 3, 4, 5,所以我们在计算的时候需要考虑所求连续因子的积 num <= N。 - 最后,我们要注意判断 N 是不是质数,如果是质数,其只有 1 和 N 两个因子,要注意同时输出(我当时就在这里犯错了)。
(2)思路
- 对于求一个数的因子,首先从 2 开始遍历,直到 √N 结束。
- 然后我们开始求连续因子,用 num 表示因子之积,count 表示连续因子的个数,从当前的数 i 开始遍历,循环继续的条件为
N % (num * j) == 0,这个不仅仅是判断下一个数是否为因子,更重要的是可以判断 num 是否大于 N,一举两得,有效的避免的易错点 2。 - 最后就是需要判断 N 是否为素数。
2、代码
#include<stdio.h>
#include<math.h>
int main()
{
long long int N, i, j, num, count, start = 0, max = 0;
scanf("%lld", &N);
for (i = 2; i < sqrt(N); i++)
{
num = 1;
count = 0;
for (j = i; N % (num * j) == 0; j++)
{
count++;
num *= j;
}
if (count > max)
{
start = i;
max = count;
}
}
if (max == 0)
{
printf("1\n");
printf("%lld\n", N);
}
else
{
printf("%lld\n", max);
for (i = start; i < start + max - 1; i++)
{
printf("%lld*", i);
}
printf("%lld\n", i);
}
return 0;
}