返回顶部

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;
    }
    
posted @ 2021-07-25 16:44  Rayotaku  阅读(42)  评论(0编辑  收藏  举报