• CF359D:Pair of Numbers——题解


    https://vjudge.net/problem/CodeForces-359D

    http://codeforces.com/problemset/problem/359/D

    题目大意:

    给一串数,问一个区间内所有的数是否能被其其中一个数所全部整除,求出满足条件的区间的长度最大值,并输出这样的区间的个数与它们的左端点。

    换句话将,求区间GCD=区间MIN的最大长度区间。

    明显st表解决。

    对于最大区间长度,二分判断即可。

    (因为在poj做过类似的题所以思路能很快……就是题看不懂有点难,所以特地给出翻译)

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    using namespace std;
    const int N=1e5*3+1;
    inline int read(){
        int X=0,w=0; char ch=0;
        while(ch<'0' || ch>'9') {w|=ch=='-';ch=getchar();}
        while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
        return w?-X:X;
    }
    inline int qpow(int a){
        if(a==0)return 1;
        return (1<<a);
    }
    int gcdd[N][30];
    int minn[N][30];
    int log[N];
    int n;
    int gcd(int a,int b){
        if(!b)return a;
        return gcd(b,a%b);
    }
    void st(){
        for(int j=1;j<=log[n];j++){
        for(int i=1;i<=n;i++){
            int p=i+qpow(j)-1;
            if(p>n)continue;
            gcdd[i][j]=gcd(gcdd[i][j-1],gcdd[i+qpow(j-1)][j-1]);
            minn[i][j]=min(minn[i][j-1],minn[i+qpow(j-1)][j-1]);
        }
        }
        return;
    }
    bool pan(int k){
        for(int i=1;i<=n;i++){
        int j=i+k;
        if(j>n)break;
        int l=log[k];
        int p=qpow(l);
        int GCD=gcd(gcdd[i][l],gcdd[j-p+1][l]);
        int MIN=min(minn[i][l],minn[j-p+1][l]);
        if(GCD==MIN)return 1;
        }
        return 0;
    }
    int len;
    void erfen(int l,int r){
        if(l>r)return;
        int mid=(l+r)>>1;
        if(pan(mid)){
        len=mid;
        erfen(mid+1,r);
        }else{
        erfen(l,mid-1);
        }
        return;
    }
    vector<int>ans;
    int main(){
        n=read();
        log[0]=-1;
        for(int i=1;i<=n;i++){
        gcdd[i][0]=minn[i][0]=read();
        log[i]=log[i>>1]+1;
        }
        log[0]=0;
        st();
        erfen(0,n-1);
        for(int i=1;i<=n;i++){
        int j=i+len;
        if(j>n)break;
        int l=log[len];
        int p=qpow(l);
        int GCD=gcd(gcdd[i][l],gcdd[j-p+1][l]);
        int MIN=min(minn[i][l],minn[j-p+1][l]);
        if(GCD==MIN)ans.push_back(i);
        }
        printf("%d %d
    ",(int)ans.size(),len);
        for(int i=0;i<ans.size();i++){
        printf("%d ",ans[i]);
        }
        return 0;
    }
  • 相关阅读:
    C++ XML文件解析
    coco2d-x create tableView
    cocos2d-x button setTitleLabel
    cocos2d-X create std colorlayer
    Windows cmd "tree"
    C/C++ std::function && std::bind
    C/C++ “std::invoke”: 未找到匹配的重载函数
    31 迭代器 Iterator 是什么?
    30 哪些集合类是线程安全的?
    02 rpx 与 px
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/7884038.html
Copyright © 2020-2023  润新知