题目描述
一个正整数 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
解析:
这道题我们有个需要注意的地方
- 答案要求输出最长连续因子序列
- 若有两个相同长度的连续因子序列,要求输出最小的连续因子序列
- 还有一个隐含条件就是题目给出的例子是630=3×5×6×7,也就是说你的连续因子序列的乘积也要整除N。
- 1不算在内
于是,我就开始了我的想法,若要找到因子,那么总体上可分为两种情况:
一种是N为质数:
那么最后输出的序列只能是N本身;
那么我们只需从2到根号下N来不断整除N
若能够整除
再判断是否是连续的因子,若是连续因子则更新当前序列长度及序列最后一个因子的值并将i累乘到current(要保证current不大于N),若不是连续因子则仅更新current为i
若不能够整除则不做任何操作
然后再判断当前序列长度是否大于当前最长序列,若大于则更新当前最长序列
最后输出结果
//我首次提交的代码如下(C++)
#include<iostream>
using namespace std;
int main()
{
// 虽然这道题最大数据在2^31,但是实际测试数据用int不够
long int N,current=1,time=1,last=0,maxtime=1,maxlast=0;
cin >> N;
for(int i=2;current*i<=N;i++){
// 判断i是否为连续因子,1不算在内
if(N%i==0&&N%(i-1)==0&&i!=2){
//current记录当前连续因子序列乘积,但没有加判断
current*=i;
// 遇到连续因子更新序列长度
time++;
// 更新当前序列最后一个因子
last=i;
}
else{
// 若不是连续因子则current重置为i
current=i;
//序列长度重置为1
time=1;
if(N%i==0)
// 更新当前子序列最后一个因子
last=i;
}
// 更新当前最长子序列长度
if(maxtime<time){
maxtime=time;
// 这一步判断其实duck不必
if(maxlast<last)
maxlast=last;
}
}
cout << maxtime << endl;
// 加一步判断num是否为质数
cout << (maxtime==1?N:maxlast-maxtime+1);
for(int i=maxlast-maxtime+2;i<=maxlast;i++)
cout << '*' << i;
return 0;
}
错误发现
- 对于60这一测试数据,忽视了最长连续子序列长度仍为N的因子,因此最长子序列不是2×3×4而是3×4×5
- 对于899这一测试数据,其因子为1、29、31、899,其最长连续因子应为29,若用上述代码提交由于maxtime初始化即为1,因此即使找到29,time置为1也不会更新maxtime,会将其当作质数进行输出
问题解决
#include<iostream>
using namespace std;
int main()
{
unsigned int N; // 也可以用long int
cin >> N;
// 该解法中定义的变量意义与上面的错误解法想同,但这里将maxtime和maxlast的初始化值都定义为了1就可以解决在根号下N范围内只有一个因子的情况
unsigned int current=1,last=0,time=0,maxlast=0,maxtime=0;
for(unsigned int i=2;i*i<=N;i++){
// 在这里较上面的解法做出了简化,易知若i和i-1是满足题目条件的因子那么他们的乘积一定能整除N
if(N%(i*(i-1))==0&&i!=2){
// 这里加入了对current的判断,只有当current是N的因子时才可更新下面这三个变量的值
if(N%(current*i)==0){
current*=i;
last=i;
time++;
}
}else{
// 如果N可被i整除则记录i,否则不做任何操作
if(N%i==0){
current=i;
// 注意此时对于899=28*31这样的数据,maxtime为0,因此可以更新maxtime和maxlast的值
time=1;
last=i;
}
}
if(maxtime<time)
{
maxtime=time;
maxlast=last;
}
}
// 对于质数的处理
if(maxtime==0){
maxtime=1;
maxlast=N;
}
cout << maxtime << endl << maxlast-maxtime+1;
for(unsigned int i=2;i<=maxtime;i++)
cout << "*" << maxlast-maxtime+i;
return 0;
}
注:
此外还有一种双重循环不断找未出现的连续因子的方法,代码比我的更加简洁,大家可以去学习一下。
链接:柳婼のblog L1-006. 连续因子-PAT团体程序设计天梯赛