[PAT解题报告] Consecutive Factors

简单题,求n的连续约数,比如n = 630 = 3 * 5 * 6 * 7,  而5,6,7是连续的,所以输出5 6 7。抽象描述是,给定n,求n % (start * (start + 1) * (start + 2) * ... * (start + len - 1)) == 0的len最长的start。如果有多个start要最小,并且1不能算。
先简单考虑一下,len最长有多长? 给定的范围是int,我们发现12!是不超过int的最大值,所以len最大才是11,即从2乘到12。(其他的11个数乘积比这个还要大)。
如果start >= sqrt(n), 则len = 1,因为start * (start + 1) > n了,所以不可能了。
于是我们枚举start只要枚举到sqrt(n)就可以了。我们就直接枚举start,然后计算出最长的len,根据刚才的分析start是sqrt(n),而len最长不过11,所以时间复杂度是11 * sqrt(n)最有, n是2^31,这个复杂度可以接受——而且len缩减很快的。
另外要注意,当结果是1的时候,因为我们希望start尽可能小,对一般的合数一定有一个不超过sqrt(n)的约数,所以我们肯定能取到这个数,比如n = 21,我们肯定能取到start = 3,结果是len = 1。而当n是质数的时候,len = 1, 而且结果只能是n本身,这点比较特殊。不过没关系,我们预先设定最好的len是0,最后循环结束发现len真的是0,即没找到解,这就说明n是质数了——因为如果有一个小于sqrt(n)的约数,len至少会被更新到1,这时我们设定len = 1, start = n即可。
其实这个题本质就是一个质数判断的变种,只是当发现一个约数x的时候,我们顺着去找x + 1, x + 2……即可。

代码:

#include <cstdio>
#include <cstring>
#include <string>
using namespace std;

int getLen(int n, int x) {
int len;
    for (len = 0; n % (x + len) == 0; n /= (x + len++))
    ;
    return len;
}
    
int main() {
int n;
    scanf("%d",&n);
    int len = 0;
    int start = 0;
    for (int i = 2; n / i >= i; ++i) {
        int may = getLen(n, i);
        if (may > len) {
            start = i;
            len = may;
        }
    }
    if (len == 0) {
        start = n;
        len = 1;
    }
    printf("%d\n",len);
    for (int i = 0; i < len; ++i) {
        if (i) {
            putchar('*');
        }
        printf("%d", start + i);
    }
    puts("");   
    return 0;
}

原题链接: http://www.patest.cn/contests/pat-a-practise/1096

全部评论
好简洁的代码
点赞 回复 分享
发布于 2016-05-13 19:29

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务