Atcoder 3857 Median Sum

Problem Statement

You are given N integers A1A2, ..., AN.

Consider the sums of all non-empty subsequences of A. There are 2N−1 such sums, an odd number.

Let the list of these sums in non-decreasing order be S1S2, ..., S2N−1.

Find the median of this list, S2N−1.

Constraints

  • 1≤N≤2000
  • 1≤Ai≤2000
  • All input values are integers.

Input

Input is given from Standard Input in the following format:

N
A1 A2  AN

Output

Print the median of the sorted list of the sums of all non-empty subsequences of A.

Sample Input 1

 

3
1 2 1

Sample Output 1

 

2

In this case, S=(1,1,2,2,3,3,4). Its median is S4=2.

Sample Input 2

 

1
58

Sample Output 2

 

58

In this case, S=(58).

    我们不妨把空集考虑进来,那么最后的答案就是 第 2^(N-1)+1 小的sum。

    显然可以直接O(N^3)dp,最后可以算出和为每个数的集合有多少个。

    然后考虑一下怎么优化这个算法。

    我们可以发现一个集合和它的补集的和总是 所有数的和,这样我们的dp数组肯定是对称的,即最后 f[0] = f[sum of a[]] ....

所以我们如果要求中位数的话,只需要知道出现过的和的中位数就行了,暴力bitset维护,常数除以了一个32.

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=2000;
int a[maxn+5],n,now;
int num[maxn*maxn+5],T;
bitset<maxn*maxn+maxn> S;
int main(){
	scanf("%d",&n),S[0]=1;
	for(int i=1;i<=n;i++){
		scanf("%d",&now);
		S|=S<<now;
	}
	for(int i=1;i<=maxn*maxn;i++) if(S[i]) num[++T]=i;
	printf("%d
",num[(T+1)>>1]);
	return 0;
}

  

原文地址:https://www.cnblogs.com/JYYHH/p/8782898.html