2019年第十届蓝桥杯 C++省赛B组 第八题:等差数列

等差数列 (时间限制: 1.0s 内存限制: 256.0MB 本题总分:20 分)

【问题描述】
数学老师给小明出了一道等差数列求和的题目。但是粗心的小明忘记了一
部分的数列,只记得其中 N 个整数。
现在给出这 N 个整数,小明想知道包含这 N 个整数的最短的等差数列有
几项?
【输入格式】
输入的第一行包含一个整数 N。
第二行包含 N 个整数 A 1 ,A 2 ,··· ,A N 。(注意 A 1 ∼ A N 并不一定是按等差数列中的顺序给出)
【输出格式】
输出一个整数表示答案。
【样例输入】
5
2 6 4 10 20
【样例输出】
10
【样例说明】
包含 2、6、4、10、20 的最短的等差数列是 2、4、6、8、10、12、14、16、
18、20。

【评测用例规模与约定】
对于所有评测用例,2 ≤ N ≤ 100000,0 ≤ A i ≤ 10 9

解题

这道题思路比较简单。首先,因为A 1 ∼ A N 不一定是按等差数列中的顺序给出,所以首先需要对于输入的数组进行一个排序。
其次,该题的关键点在于找到最大的公差,这样才能让等差数列最短。因此需要求出刚排好序的数组相邻两数的差值(如果差值为零则表示为等差数列),然后求出所有差值的最大公约数。我首先想到的是用递归:

#include <cstdio>
#include <algorithm>
using namespace std ;
const int N = 100010 ;
int a[N] ;
int max_div(int x , int y){
    int c ;
    if(y % x == 0)
        return x ;
    else{
        c = y % x ;
        x = c ;
        y = x ;
        max_div(x , y) ;
    }
}
int main(){
    int n ;
    scanf("%d", &n) ;
    for(int i = 0 ; i < n ; i ++){
        scanf("%d" , &a[i]) ;
    }
    sort(a, a + n) ;
    int d = a[1] - a[0] ;
    for(int i = 2 ; i < n ; i ++)
        d = max_div(d , a[i] - a[0]) ;
    if(!d)
        printf("%d\n" , n) ;
    else
        printf("%d\n" , (a[n - 1] - a[0]) / d + 1) ;
    return 0 ;
}

但是运行出错,原因是递归太深,爆栈了,因此换成循环。代码如下:

#include <cstdio>
#include <algorithm>
using namespace std ;
const int N = 100010 ;
int a[N] ;
int max_div(int a , int b){
    int c ;
    while(a){
        c = a ;
        a = b % a ;
        b = c ;
    }
    return b ;
}
int main(){
    int n ;
    scanf("%d", &n) ;
    for(int i = 0 ; i < n ; i ++){
        scanf("%d" , &a[i]) ;
    }
    sort(a, a + n) ;
    int d = a[1] - a[0] ;
    for(int i = 2 ; i < n ; i ++)
        d = max_div(d , a[i] - a[0]) ;
    if(!d)
        printf("%d\n" , n) ;
    else
        printf("%d\n" , (a[n - 1] - a[0]) / d + 1) ;
    return 0 ;
}

猜你喜欢

转载自blog.csdn.net/just_gong/article/details/106695956