7-84 连续因子 (20 分)
一个正整数 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
code1:
#include<stdio.h>
#include<math.h>
int main(){
long n,i,j,cnt=0,max,num_max=0,sum=0,mul=1;
scanf("%ld",&n);
long a[500];
long b[500];
for(i=2;i<=sqrt(n)+10;i++){ //求出n的因数,放入数组a,数组b初始化为1;
if(n%i==0){
a[cnt]=i;
b[cnt]=1;
cnt++;
}
}
max=b[0]; //求出b数组从左边数的最大数
for(i=0;i<cnt;i++){ //a[i]从0开始到最后遍历
mul=a[i];
for(j=1;i+j<cnt;j++){ //从a[i]开始检查是否递加1;
mul*= a[i+j];
if(a[i+j]-a[i+j-1]==1&&n%mul==0){ //两个条件:相邻因数差为1,因数乘积可以被n整除
b[i] += 1; //b数组记录a数组的连续数的个数
if(max<b[i]){ //求b数组中最大数,'<'保证如果相等,就不会采用右侧的
max=b[i];
num_max=i;
}
continue;
}else{
break;
}
}
}
if(cnt==0){ //对质数,直接输出。
printf("1\n%d",n);
return 0;
}
printf("%ld\n",max);
for(i=num_max;i<num_max+max;i++){
printf("%ld",a[i]);
if(i!=num_max+max-1) printf("*");
}
return 0;
}
code2:
#include<stdio.h>
#include<math.h>
int main(){
int n,mul,max,flag=0;
scanf("%d",&n);
int i,j,max_i=0,max_j=0;
for(i=2;i<sqrt(n)+1;i++){
mul=i;
for(j=1;n%mul==0;j++){
flag=1;
if(max_j<j){
max_j=j;
max_i=i;
}
mul*=j+i;
}
}
if(flag){
printf("%d\n",max_j);
for(i=max_i;i<max_i+max_j;i++){
printf("%d",i);
if(i!=max_i+max_j-1)printf("*");
}
}else{
printf("%d\n",1);
printf("%d\n",n);
}
return 0;
}
总结:
1. N的连续因子只能出现在0~N的开方之间。如果寻找N的因子,遍历到N,则会超时。有一种特殊情况,就是N开方两侧的数字连续,如22052=148*149,22052的开方=148.49。所以遍历的时候寻找到N的开方+1;
2. 由于以上情况,所以遍历不到N,如果是质数,则找不到因数,所以单独处理。
3.code2为code1的优化,发现没必要非要做出数组来。找出最大连续数的初始数及连续数,就可以还原出具体值来。