您的位置:首页 > 其它

【DP】【bitset】17.6.4 均分 题解

2017-06-05 20:57 141 查看




暴力就是做背包,然后找最接近一半的可以凑出来的值

由n<=10^6且sigma a[i]<=10^6我们可以知道不相等的a[i]最多有根号10^6种

那么就从一个10^6个物品的背包变成了10^3个物品的每个物品可以有多个的背包

用二进制拆包优化,复杂度为10^3*10^6*log

用bitset优化,再除以32

事实上可以参考2015年任之洲集训队论文,提出了一种n log n的近似算法,效果也很优秀,审题人并未实现,不过应该可以AC,因为曾经用这个算法AC过其他的带权均分问题

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<bitset>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#define INF_min 1e9
using namespace std;
int T,n,tot,ans;
int a[1000001],cnt[1001];
bitset <1000005> bit;
int main()
{   freopen("share.in","r",stdin);
freopen("share.out","w",stdout);
scanf("%d",&T);
while(T--)
{
bit.reset();tot=0;
memset(cnt,0,sizeof(cnt));
scanf("%d",&n);
bit[0]=1;
for(int i=1;i<=n;i++){scanf("%d",&a[i]);tot+=a[i];}
for(int i=1;i<=n;i++)
{
if(a[i]<sqrt(tot))cnt[a[i]]++;
else bit|=bit<<a[i];
}
int t=1;
for(int i=1;i<=sqrt(tot);i++)
{
t=1;
while(cnt[i])
{
if(cnt[i]>=t)
{
bit|=bit<<(i*t);
cnt[i]-=t;
t*=2;
}
else {bit|=bit<<(cnt[i]*t);cnt[i]=0;}
}
}
ans = INF_min;
for(int i=0;i<=bit.size();i++) if(bit[i]) ans = min(ans, abs(i-(tot-i)));
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: