Codeforces Round #731 (Div. 3) F. Array Stabilization (GCD version) (st表预处理,二分答案)
-
题意:有一组序列\(a=[a_0,a_1,...,a_{n-1}]\),每次操作得到一组新序列\(b=[b_0,b_1,...,b_{n-1}]\),\(b[i]=gcd(a_i,a_{(i+1)\mod n})\),问你最少操作几次可以是新序列所有元素相等.
-
题解:所有元素相等,即最后所有\(b_i=gcd({a_0,a_1,...,a_{n-1}})\).直接st表预处理,然后二分答案check一下就行.
-
代码:
#include <bits/stdc++.h> #define ll long long #define fi first #define se second #define pb push_back #define me memset #define rep(a,b,c) for(int a=b;a<=c;++a) #define per(a,b,c) for(int a=b;a>=c;--a) const int N = 1e6 + 10; const int mod = 1e9 + 7; const int INF = 0x3f3f3f3f; using namespace std; typedef pair<int,int> PII; typedef pair<ll,ll> PLL; ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;} ll lcm(ll a,ll b) {return a/gcd(a,b)*b;} int _; int n; int a[N]; int d; int lg[N]; int dp[N][50]; void lg_init(){ for(int i=1;i<=2*n;++i){ int k=0; while(1<<(k+1)<=i) k++; lg[i]=k; } } void RMQ_init(){ for(int i=1;i<=2*n;++i) dp[i][0]=a[i]; for(int j=1;(1<<j)<=2*n;++j){ for(int i=1;i+(1<<j)-1<=2*n;++i){ dp[i][j]=gcd(dp[i][j-1],dp[i+(1<<(j-1))][j-1]); } } } int RMQ(int l,int r){ int k=lg[r-l+1]; return gcd(dp[l][k],dp[r-(1<<k)+1][k]); } bool check(int x){ for(int i=1;i<=n;++i){ if(RMQ(i,i+x)!=d) return false; } return true; } int main() { ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); cin>>_; while(_--){ cin>>n; d=0; for(int i=1;i<=n;++i){ cin>>a[i]; } rep(i,n+1,2*n) a[i]=a[i-n]; rep(i,1,n) d=gcd(d,a[i]); lg_init(); RMQ_init(); int l=0,r=n; while(l<r){ int mid=(l+r)>>1; if(check(mid)) r=mid; else l=mid+1; } cout<<l<<'\n'; } return 0; }
𝓐𝓬𝓱𝓲𝓮𝓿𝓮𝓶𝓮𝓷𝓽 𝓹𝓻𝓸𝓿𝓲𝓭𝓮𝓼 𝓽𝓱𝓮 𝓸𝓷𝓵𝔂 𝓻𝓮𝓪𝓵
𝓹𝓵𝓮𝓪𝓼𝓾𝓻𝓮 𝓲𝓷 𝓵𝓲𝓯𝓮