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