题目大意:
这道题目给了一个序列和给定的m ,要求在这个序列中求若干个数使得他们的和对m取模后最大,然后数据量给定的是35

题目分析:开始的时候,想到对于求和取模最大,感觉并没有什么可以找的规律,唯一的方法就是暴力,但是对于35个数来说,每个数都有取或者不取的可能,2^35远远超过了时间上限,所以显然不能直接暴力,所以这道题稍微转了一个弯,先将所有数据一分为二,暴力求出所有的情况,然后两边取模后,对一边的每一种情况,与另一边相加,二分求取模的最大,再求总的取模最大就行了,这样的复杂度就能控制住了

Ac代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int INF = 0x3f3f3f3f;
const long long inf =1e18;
const ll maxn = (1<<18)+50;
const int mod =1e9+7;
ll T,n,m,k;
ll a[50];
ll _left[maxn];
ll _right[maxn];

bool check(ll k,ll mid)
{
    if(k+_right[mid]<m)
    {
        return true;
    }
    return false;
}
bool check2(ll k,ll mid)
{
    if(k+_right[mid]<m*2)
    {
        return true;
    }
    return false;
}
int main()
{

    ll allans=0;
    memset(_left,0,sizeof(_left));
    scanf("%I64d%I64d",&n,&m);
    for(int i=1; i<=n; i++)
    {
        scanf("%I64d",&a[i]);
    }
    for(int i=1; i<(1<<((n/2))); i++)
    {
        for(int j=1; (1<<(j-1))<=i; j++)
        {
            int s=1<<(j-1);
            if(i&s)
            {
                _left[i]=(_left[i]+a[j])%m;
                allans=max(allans,_left[i]);
            }
        }
        // cout<<i<<" "<<_left[i]<<endl;
    }
    sort(_left+1,_left+(1<<(n/2)));
    memset(_right,0,sizeof(_right));
    int ends=(1<<((n-n/2)));
    _right[ends]=inf;
    for(int i=1; i<(1<<((n-n/2))); i++)
    {
        for(int j=1; (1<<(j-1))<=i; j++)
        {
            int s=1<<(j-1);
            if(i&s)
            {
                _right[i]=(_right[i]+a[j+n/2])%m;
                allans=max(_right[i],allans);
            }
        }
        // cout<<i<<" "<<_right[i]<<endl;
    }
    sort(_right+1,_right+(1<<(n-n/2)));
    for(int i=1; i<(1<<((n/2))); i++)
    {
        ll k=_left[i];
        ll st=0,ed=(1<<(n-n/2));
        while(ed-st>1)
        {
            ll mid=st+(ed-st)/2;
            // if(i==2)cout<<"***->"<<mid<<endl;
            if(check(k,mid))
            {
                st=mid;
            }
            else ed=mid;
            // if(i==2)cout<<"$$$->"<<st<<endl;
        }
        ll ans1=(_right[st]+k)%m;
        // cout<<i<<" "<<ans1<<endl;
        allans=max(ans1,allans);
        st=0;
        ed=(1<<(n-n/2));
        while(ed-st>1)
        {
            ll mid=st+(ed-st)/2;
            if(check2(k,mid))
            {
                st=mid;
            }
            else ed=mid;
        }
        ll ans2=(_right[st]+k)%m;
        allans=max(ans2,allans);

    }
    printf("%I64d\n",allans);
    return 0;
}