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;
}

  

转载于:https://www.cnblogs.com/guangheli/p/9922131.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值