CF1547 F. Array Stabilization (GCD version)

Problem - 1547F - Codeforces

 

题意:

有一个a数组,每次可以把所有的a[i]变为gcd(a[i],a[(i+1)%n])

问最少多少次可以让a数组都变为相同的值

 

第i次操作相当于把a[i]变为原始的区间[i,(i+k)%n]的gcd

所以题目相当于问最小的k,满足所有的区间[i,(i+k)%n]的gcd都相等

二分k,然后st表就可以了

因为是模意义下的循环区间

所以可以把a数组复制一遍

 

#include<bits/stdc++.h>

using namespace std;

#define N 400003

int n,a[N];
int st[N][18];
int l2[N];

int find(int l,int r)
{
    int len;
    len=l2[r-l+1];
    return __gcd(st[l][len],st[r-(1<<len)+1][len]);
}


bool check(int k)
{
    int g=find(0,k-1);
    for(int i=1;i<n;++i)
        if(find(i,i+k-1)!=g) return false;
    return true;
}

int main()
{
    int T,l,r,mid,ans;
    bool tag;
    for(int i=2;i<N;++i) l2[i]=l2[i>>1]+1;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=0;i<n;++i) scanf("%d",&a[i]);
        tag=false;
        for(int i=1;i<n && !tag;++i)
            if(a[i]!=a[i-1]) tag=true;
        if(!tag)
        {
            printf("0\n");
            continue;
        }
        for(int i=0;i<n;++i) a[n+i]=a[i];
        for(int i=0;i<n+n;++i) st[i][0]=__gcd(a[i],a[i+1]);
        for(int i=1;1<<i<n;++i)
            for(int j=0;j+(1<<i-1)<n+n;++j)
                st[j][i]=__gcd(st[j][i-1],st[j+(1<<i-1)][i-1]); 
        l=1;
        r=n-1;
        while(l<=r)
        {
            mid=l+r>>1;
            if(check(mid)) 
            {
                ans=mid;
                r=mid-1;
            }
            else l=mid+1;
        }
        printf("%d\n",ans);
    }
}

 

posted @ 2021-10-02 11:55  TRTTG  阅读(60)  评论(0编辑  收藏  举报