CodeForces - 1547F Array Stabilization (GCD version)(ST表+二分)
作者:互联网
题目链接:点击查看
题目大意:给出一个长度为 n n n 的数组 a a a,下标从 0 0 0 开始,每次操作分为两个步骤:
- 构建出数组 b b b,有 b i = g c d ( a i , a ( i + 1 ) m o d n ) b_i=gcd(a_i,a_{(i+1)\mod n}) bi=gcd(ai,a(i+1)modn)
- 用数组 b b b 覆盖数组 a a a
问至少需要操作多少次,才能使得数组 a a a 的每个元素都相等
题目分析:
方便起见,下文中的下标 ( i + 1 ) m o d n (i+1)\mod n (i+1)modn 统一用 i + 1 i+1 i+1 表示
需要分析出:
- 操作 0 0 0 次, a i = a i a_i=a_i ai=ai
- 操作 1 1 1 次, a i = g c d ( a i , a i + 1 ) a_i=gcd(a_i,a_{i+1}) ai=gcd(ai,ai+1)
- 操作 2 2 2 次, a i = g c d ( g c d ( a i , a i + 1 ) , g c d ( a i + 1 , a i + 2 ) ) = g c d ( a i , a i + 1 , a i + 2 ) a_i=gcd(gcd(a_i,a_{i+1}),gcd(a_{i+1},a_{i+2}))=gcd(a_i,a_{i+1},a_{i+2}) ai=gcd(gcd(ai,ai+1),gcd(ai+1,ai+2))=gcd(ai,ai+1,ai+2)
- …
- 操作 k k k 次, a i = g c d ( a i , a i + 1 , . . . , a i + k ) a_i=gcd(a_i,a_{i+1},...,a_{i+k}) ai=gcd(ai,ai+1,...,ai+k)
不难看出当 k k k 取 n n n 时,所有的数字都等于 n n n 个数的最大公约数,所以操作次数最多有 n n n 次,最少有 0 0 0 次
显然 k k k 具有单调性,所以考虑二分 k k k,现在问题是如何快速去求区间 g c d gcd gcd,这里给出两种方法,第一种就是最简单的线段树,但是如果严格来计算复杂度的话,线段树拆分区间一层 l o g log log, g c d gcd gcd 一层 l o g log log,所以总的时间复杂度是 n l o g 3 n nlog^3n nlog3n 的,但好像是可以通过本题的?
又因为是静态查询,所以不妨直接打个 S T ST ST 表,这样可以优化掉一层 l o g log log,复杂度是 n l o g 2 n nlog^2n nlog2n 的,但 g c d gcd gcd 的那层 l o g log log 好像很小,所以近似于 n l o g n nlogn nlogn 的
循环取模的话,只需要将数组复制一遍就可以了
代码:
// Problem: F. Array Stabilization (GCD version)
// Contest: Codeforces - Codeforces Round #731 (Div. 3)
// URL: https://codeforces.com/contest/1547/problem/F
// Memory Limit: 512 MB
// Time Limit: 4000 ms
//
// Powered by CP Editor (https://cpeditor.org)
// #pragma GCC optimize(2)
// #pragma GCC optimize("Ofast","inline","-ffast-math")
// #pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
#define lowbit(x) x&-x
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
template<typename T>
inline void read(T &x)
{
T f=1;x=0;
char ch=getchar();
while(0==isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(0!=isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
x*=f;
}
template<typename T>
inline void write(T x)
{
if(x<0){x=~(x-1);putchar('-');}
if(x>9)write(x/10);
putchar(x%10+'0');
}
const int inf=0x3f3f3f3f;
const int N=1e6+100;
int a[N],st[N][20],n;
void ST_build()
{
for(int i=1;i<=n<<1;i++)
st[i][0]=a[i];
for(int i=1;i<=20;i++)
for(int j=1;j+(1<<i)-1<=n<<1;j++)
st[j][i]=__gcd(st[j][i-1],st[j+(1<<(i-1))][i-1]);
}
int ST_query(int l,int r)
{
int k=log2(r-l+1);
return __gcd(st[l][k],st[r-(1<<k)+1][k]);
}
bool check(int len) {
int mark=ST_query(1,1+len);
for(int i=2;i<=n;i++) {
if(mark!=ST_query(i,i+len)) {
return false;
}
}
return true;
}
int main()
{
#ifndef ONLINE_JUDGE
// freopen("data.in.txt","r",stdin);
// freopen("data.out.txt","w",stdout);
#endif
// ios::sync_with_stdio(false);
int w;
cin>>w;
while(w--) {
read(n);
for(int i=1;i<=n;i++) {
read(a[i]);
a[i+n]=a[i];
}
ST_build();
int l=0,r=n,ans=-1;
while(l<=r) {
int mid=(l+r)>>1;
if(check(mid)) {
r=mid-1;
ans=mid;
} else {
l=mid+1;
}
}
cout<<ans<<endl;
}
return 0;
}
标签:Stabilization,GCD,ai,1547F,ST,int,log,include,gcd 来源: https://blog.csdn.net/qq_45458915/article/details/118681479