• Array Stabilization (GCD version)(ST表+二分+题目大意的处理+gcd)


    ST

    • (利用二进制进行跳(优化时间复杂度))(预处理 nlogn) 查询 O(1); 
    • 处理 RMQ和GCD问题(重复计算部分无所谓)

    arr[i][j] 代表 i —— i+(1<<j)-1 这一区间的值, 区间长度为 1<<j.

    void init()
    {
        
       for(ri i=1;i<=n;i++) arr[i][0]=val[i];
       for(ri i=1;i<=log2(n);i++)
       {
            for(ri j=1;j+(1<<i)-1<=n;j++)
            {
                arr[j][i]=gcd(arr[j][i-1],arr[j+(1<<(i-1))][i-1]);
         }
       }
        
    }
    
    int qu(int a,b)
    {
        int k=log2(b-a+1);
        return gcd(arr[a][k],arr[r-(1<<(k))+1][k]);
     } 
     
    View Code

    推荐博客 :浅谈ST表 - 自为风月马前卒 - 博客园 (cnblogs.com)

    本题思路:

    • 每一次的转化,对于一个基本元素就是 (ai+ai+1+ai+2......)这种对题目的预处理思维很常见的。
    • 利用gcd的性质,满足结合律,谁便结合,让他们都相等就是 ai=gcd(all)
    • 利用二分求K
    • 利用ST判断可行不
    #include <bits/stdc++.h>
    using namespace std;
    #define ri register int
    #define  M 200005
    
    template <class G > void  read(G &x)
    {
        x=0;int f=0;char ch=getchar();
        while(ch<'0'||ch>'9'){f|=ch=='-';ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        x=f?-x:x;
        return ;
     } 
     
    int n,m;
    int T,val[M];
    int st[M][30];
    int gg;
    int gcd(int a,int b)
    {
        if(a<b) swap(a,b);
        if(a%b!=0)
        {
            return gcd(b,a%b);
        }
        else return b;
    }
    void init(){
        
        for(ri i=1;i<=n;i++) st[i][0]=val[i];
        for(ri i=1;i<=log2(n);i++)
        {
            for(ri j=1;j+(1<<i)-1<=n;j++)
            {
                st[j][i]=gcd(st[j][i-1],st[j+(1<<(i-1))][i-1]);
            }
        }
    }
    int qu(int l,int r)
    {
        int k=log2(r-l+1);
        return gcd(st[l][k],st[r-(1<<k)+1][k]);
    }
    bool ck(int a)
    {
        for(ri i=1;i<=n;i++)
        {
            if(i+a<=n)
            {
                if(qu(i,i+a)==gg) continue;
                else return 0;
            }
            else
            {
                if(gcd(qu(i,n),qu(1,(i+a-n)))==gg) continue;
                else return 0;
            }
        }
        return 1;
    }
    
    int main(){
        
        read(T);
        while(T--)
        {
            read(n);
            for(ri i=1;i<=n;i++)
            {
                read(val[i]);
            }
            bool ff=0;
            gg=gcd(val[1],val[2]);
            for(ri i=2;i<=n;i++)
            {
                if(val[i]!=val[1]) ff=1;
                gg=gcd(val[i],gg);    
            }
            if(ff==0)
            {
                printf("0\n");
                continue;
            }
            init();
            int l=1,r=n;
            while(l<r)
            {
                int mid=(l+r)>>1;
                if(ck(mid)) r=mid;
                else l=mid+1;
            }
            printf("%d\n",l);
        }
        
    } 
    View Code
  • 相关阅读:
    增加Tomcat内存大小
    JAVA中的JSON
    js判断中文字符长度
    2016总结
    JavaScript 字符串实用常用操作
    Java文件操作
    hadoop中hbase出现的问题
    static_cast静态类型转换指针导致Release程序随机崩溃报错
    解决: error C2236: 意外的标记“class”。是否忘记了“;”?
    游戏操作杆代码
  • 原文地址:https://www.cnblogs.com/Lamboofhome/p/16142042.html
Copyright © 2020-2023  润新知