2

题目大意:

给出一个正整数N,求一段连续的整数, 使得N能被这段连续整数的乘积整除。如果有多个方案,输出连续整数个数最多的方案;如果还有多种方案,输出其中第一个数最小的方案。

算法思路:

刚开始审题不当以为是质因子分解,导致浪费了很多时间,该题的想法也比较直观,我们遍历从2到N之间的每一个数字,用consecutiveMulti保存每一个可以被N整除的连续序列的乘积,并且使用len保存最长的序列长度,begin保存最长的序列的起始数字,让consecutiveMulti不断累乘直到不能被N整除位置(就类似于从2开始一直乘以3,4,5,6...直到N不能整除该连续乘积为止,然后再接着从3开始一直乘以4,5,6,7,8...以此类推),然后更新长度len和起始位置begin,这里得注意i的含义是每一个连续序列的起始位置,我们这里使用nextNum保存当前序列的下一个待乘的数字,初始为i,然后在循环中,consecutiveMulti会乘以nextNum,并且其长度可以使用nextNum-i+1来代替,因为在数字inextNum之间的数字都是连续的,每次更新nextNum加一即可。其实在这里不用遍历2到N,只用遍历到根号N即可,因为,第一,不存在2个因子都大于根号N。第二,N如果存在大于根号N的因子一定无法和前面的因子组成连续序列。第三,如果在2到根号N中没有N的因子,那么在根号N和N之间也必定不会有N的因子,N的因子只有1和N本身,但是题目由于对于1不考虑,所以在2和根号N之间没有解的时候只有长度为1的连续序列N。

提交结果:

image.png

AC代码:

#include <cstdio>
#include <cmath>

using namespace std;

int main(){
    int N;
    scanf("%d",&N);
    int sqrt_N = (int)sqrt(N * 1.0);
    int begin = 0;
    int len = 0;
    for (int i = 2; i <=sqrt_N ; ++i) {
        int consecutiveMulti = 1;// 从数字i开始的部分连续乘积
        int nextNum = i;//当前序列后面待乘的一个数字
        while (true){
            consecutiveMulti *= nextNum;
            if(N%consecutiveMulti!=0) break;// 无法整除当前序列退出循环
            // 可以整除,更新长度
            if(len<nextNum-i+1){
                len = nextNum-i+1;
                begin = i;
            }
            ++nextNum;// 更新下一个待乘的数字
        }
    }
    if(len==0){
        // 说明不存在2到根号N的数字部分乘积可以整除N,也即是当前的N只有一个因子(它自己)。
        printf("1\n%d",N);
    }else {
        printf("%d\n",len);
        for (int i = begin; i < begin+len; ++i) {
            printf("%d",i);
            if(i<begin+len-1) printf("*");
        }
    }
    return 0;
}

乔梓鑫
569 声望17 粉丝

主要分享个人学习经验和心得