888E - Maximum Subsequence 中途相遇法

Code:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;
void setIO(string a){freopen((a+".in").c_str(),"r",stdin),freopen((a+".out").c_str(),"w",stdout);}
void shutIO(){ fclose(stdin),fclose(stdout);}

#define ll long long 
#define maxn 50
int arr[maxn],brr[maxn],p[maxn];
int A[5000000],B[5000000],cnta,cntb;
bool cmp1(int i,int j){return i<j;}        //min->max
bool cmp2(int i,int j){return i>j;}        //max->min
int main(){
    //setIO("sweet");
    int n,mod,l,r;
    scanf("%d%d",&n,&mod);
    l=n/2,r=n-l;
    for(int i=1;i<=l;++i)scanf("%d",&arr[i]);
    for(int i=1;i<=r;++i)scanf("%d",&brr[i]);
    for(int i=1;i<=22;++i) p[i]=(1<<i);
    for(int sta=1;sta<p[l];++sta){
        int k=sta,len=1,sum=0;
        while(k>0){
            if(k&1) sum=((ll)(sum+arr[len])%mod);
            ++len;
            k>>=1;
        }
        A[++cnta]=sum;
    }
    for(int sta=1;sta<p[r];++sta){
        int k=sta,len=1,sum=0;
        while(k>0){
            if(k&1) sum=((ll)(sum+brr[len]))%mod;
            ++len;
            k>>=1;
        }
        B[++cntb]=sum;
    }
    sort(A+1,A+1+cnta,cmp1);
    sort(B+1,B+1+cntb,cmp2);
    int i,j,ans=0;
    for(i=1,j=1;i<=cnta&&j<=cntb;){
        while(A[i]+B[j]>=mod && j<=cntb) ++j;
        if(j>cntb) break;
        while(A[i]+B[j]<mod && i<=cnta) ans=max(ans,A[i]+B[j]),++i;
        if(i>cnta) break;
    }

    sort(A+1,A+1+cnta,cmp2);
    sort(B+1,B+1+cntb,cmp1);
    for(i=1,j=1;i<=cnta&&j<=cntb;){
        while(A[i]+B[j]>=mod && i<=cnta) ++i;
        if(i>cnta) break;
        while(A[i]+B[j]<mod && j<=cntb) ans=max(ans,A[i]+B[j]),++j;
        if(j>cntb) break;
    }
    printf("%d",ans);
   // shutIO();
    return 0;
}

  

posted @ 2018-11-07 13:55  EM-LGH  阅读(295)  评论(0编辑  收藏  举报