AtCoder C - Median Sum //bitset 01背包优化
C - Median Sum
Time limit : 2sec / Memory limit : 512MB
Score : 700 points
Problem Statement
You are given N integers A1, A2, ..., 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 S1, S2, ..., 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
Copy
3 1 2 1
Sample Output 1
Copy
2
In this case, S=(1,1,2,2,3,3,4). Its median is S4=2.
Sample Input 2
Copy
1 58
Sample Output 2
Copy
58
In this case, S=(58).
题意:给一个数组A,求出所有的subsequences的和,再sort,求出中间那个和。
如果含空集,那么一个subsequence x一定有对应的(A-x),那么再最中间的两个subsequence一定是最接近sum/2的,因为没有0,所以最中间那个比sun/2大,问题就转化为01背包。
此题,V=4e6,N=2e3,VN=8e9,会超时,用bitset优化,(会跑的快32或64倍- - )这样就可以过。
因为dp[i]=max(dp[i],dp[i-ai]),那么左移的操作就可以做到这个目的。
比如101011,ai=3,101011<<3=101011000,101011000|101011=10111011就相当于用ai更新了一次。
#include<bits/stdc++.h>
using namespace std;
#define LL long long
const LL mod = 1000000007;
const int MX = 2e3+1;
bitset<MX*MX>bs;
int main(){
bs[0]=1;
int n,s=0,sc;scanf("%d",&n);for(int i=1;i<=n;i++){
scanf("%d",&sc);bs=bs|(bs<<sc);s+=sc;
}
for(int i=(s+1)/2;i<=s;i++)if(bs[i]){printf("%d",i);break;}
return 0;
}