题意: n 个数,选出其中 k 个数,使得他们的和对 m 取模后最大。 输出这个最大值。
tags:注意到 n 很小, 所以折半枚举。
// E #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b; i>=a; --i) #define mes(a,b) memset(a,b,sizeof(a)) #define INF 0x3f3f3f3f #define MP make_pair #define PB push_back #define fi first #define se second typedef long long ll; const int N = 800005; ll n, m, s1[N], s2[N], a[N]; int main() { scanf("%lld%lld", &n, &m); rep(i,1,n) scanf("%lld", &a[i]); int n1 = n/2, n2 = n-n1; int cnt1 = (1<<n1)-1, cnt2 = (1<<n2)-1; for(int i=0; i<=cnt1; ++i) { ll num = 0; for(int j=0; j<n1; ++j) if((i>>j)&1) num += a[j+1]; s1[i] = num%m; } for(int i=0; i<=cnt2; ++i) { ll num = 0; for(int j=0; j<n2; ++j) if((i>>j)&1) num += a[n1+j+1]; s2[i] = num%m; } sort(s2, s2+cnt2+1); sort(s1, s1+cnt1+1); cnt1 = unique(s1, s1+cnt1+1) - s1; cnt2 = unique(s2, s2+cnt2+1) - s2; --cnt1, --cnt2; ll ans = 0; for(int i=0; i<=cnt1; ++i) { ll num = m-s1[i]; int pos = lower_bound(s2, s2+cnt2+1, num) - s2; if(pos==cnt2+1 || pos>0) ans = max(ans, s1[i]+s2[pos-1]); } printf("%lld\n", ans); return 0; }