其他分享
首页 > 其他分享> > CodeForces - 1547F Array Stabilization (GCD version)(ST表+二分)

CodeForces - 1547F Array Stabilization (GCD version)(ST表+二分)

作者:互联网

题目链接:点击查看

题目大意:给出一个长度为 n n n 的数组 a a a,下标从 0 0 0 开始,每次操作分为两个步骤:

  1. 构建出数组 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​)
  2. 用数组 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 表示

需要分析出:

  1. 操作 0 0 0 次, a i = a i a_i=a_i ai​=ai​
  2. 操作 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​)
  3. 操作 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​)
  4. 操作 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