P8792 [蓝桥杯 2022 国 A] 最大公约数

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string>
#include <cmath>
#define For(i, j, n) for(int i = j ; i <= n ; ++i)
using namespace std;

const int N = 1e5 + 5;

int gcd(int x, int y)
{
    return y?gcd(y, x%y):x;
}

int n, a[N];
int st[N][17];
int Log[N];
int cnt;

void build_st()
{
    Log[0] = -1;
    for(int i = 1; i <= n; i++)
        Log[i] = Log[i/2] + 1;
    for(int i = 1; i <= n; i++)
        st[i][0] = a[i];
    for(int k = 1; k <= 16; k++)
        for(int i = 1; i + (1 << (k - 1)) <= n; i++)
            st[i][k] = gcd(st[i][k - 1], st[i + (1 << (k - 1))][k - 1]);
}

int query(int l, int r)
{
    if(r < l)
        return 0x3f3f3f3f;
    int t = Log[r - l + 1];
    return gcd(st[l][t], st[r - (1 << t) + 1][t]);
}

int solve()
{
    int ans = n;
    if(query(1, n) > 1)
        return -1;
    if(cnt)
        return n - cnt;
    int i = 1;
    for(int j = 1; j <= n; j++)
    {
        while(i < j && query(i + 1, j) == 1)
            i++;
        //cout << "R:" << i << " " << j << endl;
        if(query(i, j) == 1)
            ans = min(ans, j - i + 1);
    }
    return ans + n - 2;
}

int main()
{
    scanf("%d", &n);
    for(int i = 1; i <= n; i++)
        scanf("%d", &a[i]), cnt += (a[i] == 1);
    build_st();
    printf("%d\n", solve());
    return 0;
}

数组中含有1的情况要进行特判。

posted @ 2024-03-28 09:33  Gold_stein  阅读(13)  评论(0编辑  收藏  举报