ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 백준 23888 (등차수열과 쿼리)
    백준 문제 2022. 1. 12. 18:40
    728x90

    문제

     

    23888번: 등차수열과 쿼리

    등차수열은 연속하는 두 항의 차이가 일정한 수열을 뜻한다. 연속한 두 항 중 뒷항에서 앞항을 뺀 값을 공차라고 한다. 초항이 $a$이고 공차가 $d$인 등차수열이 주어진다. 수열의 $i$번째 원소를

    www.acmicpc.net

    초항 a와 공차 d가 주어지면 쿼리의 수에 따라 합이나 최대공약수를 출력하는 문제입니다.

    쿼리가 1이고 구간 l과 r이 주어지면 [a(l) 부터 a(r)] 까지의 구간에 있는 수열의 합을 구하는 것입니다.

    쿼리가 2이면 구간 l과 r이 주어지면 [a(l) 부터 a(r)] 까지의 구강에 있는 수열들의 최대공약수를 구하는것입니다.

     

    먼저 쿼리 1의 해당 구간에 있는 수열들의 합을 구하기 위해서는 prefix sum 알고리즘을 사용하였습니다.

    1
    2
    3
    4
    sumsum[1= a;
        for (ull i = 2; i < 1010101; i++) {
            sumsum[i] = sumsum[i - 1+ a + (i - 1* d;
        }
    cs

    배열에 미리 누적합을 저장하는 방법입니다.

    첫번째 항은 그대로 자기자신이므로 sumsum[1] = a 로 설정해줍니다.

    그 다음 for문에서 sumsum[i]는 지금까지 누적합(sumsum[i - 1]) + 자기자신(a + (i - 1) * d) 을 해주면 됩니다.

     

    쿼리 2는 최대공약수의 성질을 이용하였습니다.

    gcd(a + cb , b) = gcd(a, b)

    gcd(a, a + d) = gcd(a, d) 

    gcd(a, b, c) = gcd(gcd(a, b), c)

    1
    2
    if (l == r)cout << a + (l - 1* d<<'\n';
    else cout << gcd(a, d) << '\n';
    cs

    주어진 수열은 공차가 d로 일정한 수열이므로 어느 구간에서나 모든 수열의 최대공약수는 gcd(a, d)를 만족합니다.

    따라서 쿼리 2는 gcd(a, d) 이고 만약 l과 r이 같다면 그냥 그 구역에 있는 수를 출력하면 되므로 따로 코딩해줘야 합니다.


    전체 코드 입니다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    #include<iostream>
    #include<algorithm>
    #include<climits>
    #include<string>
    #include<vector>
    #include<queue>
    #include<stack>
    #include<deque>
    #include<cmath>
    #include<time.h>
    #include<cstring>
    #include<cmath>
    using namespace std;
    using ll = long long;
    using ull = unsigned long long;
    ull a, d;
    ull num, l, r;
    ull sumsum[1010101];
    ull q;
    ll gcd(ull x, ull y);
    int main() {
        ios_base::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL);
        cin >> a >> d;
     
        sumsum[1= a;
        for (ull i = 2; i < 1010101; i++) {
            sumsum[i] = sumsum[i - 1+ a + (i - 1* d;
        }
        cin >> q;
        for (num, l, r; q > 0; q--) {
            cin >> num >> l >> r;
            if (num == 1)
                cout << sumsum[r] - sumsum[l - 1<< '\n';
            else
                if (l == r)cout << a + (l - 1* d<<'\n';
                else cout << gcd(a, d) << '\n';
        }
        
     
        return 0;
    }
    ll gcd(ull x, ull y) {
        if (!y)return x;
        return gcd(y, x % y);
    }
     
     
     
    cs

    '백준 문제' 카테고리의 다른 글

    백준 14565 (역원(Inverse) 구하기) c++  (0) 2022.01.14
    백준 24040 (예쁜 케이크) c++  (0) 2022.01.14
    백준 2026 (소풍) c++  (0) 2022.01.11
    백준 2239 (스도쿠) c++  (0) 2022.01.11
    백준 14889 (스타트와 링크) c++  (0) 2022.01.10
Designed by Tistory.