codeforces 888E Maximum Subsequence

来源:互联网 发布:常州茗顺网络 编辑:程序博客网 时间:2024/05/17 00:13

题目大意:
这道题目给了一个序列和给定的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;}
阅读全文
0 0
原创粉丝点击