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);
}
}
作者:xxy
本文版权归作者所有,转载请用链接,请勿原文转载,Thanks♪(・ω・)ノ。