P3067 [USACO12OPEN] Balanced Cow Subsets G

/*
https://www.luogu.com.cn/problem/P3067
1~an 找出子集 且子集可以 分成两部分 和相同 的 小子集的并 折半搜索 本质是 拆分问题规模 用 O(N^2) 算法解决问题 dfs 1~n>>1 ai-bi 的种类 +dfs n>>1+1~n ci-di 若 a-b==c-d -> a+d== b+c -1、0、1 表示 删减/不选/加 -》 找出子集 最重要 而不是 子集的分法-》 0/1 即可 */ /* 4 1 2 3 4 3 */ #include<cstdio> #include<iostream> #include<algorithm> #include<cmath> #include<string.h> //#include<queue> //#include<vector> #include<bits/stdc++.h> #define ll long long #define ddd printf("-----------------------\n"); using namespace std; const int maxn=1e1 +10; const int mod=998244353; const int inf=0x3f3f3f3f; int n,a[100],cnt,ans[2000001],res; map<int,int > mp; vector<int> p[2000001]; void dfs1(int l,int r,int sum,int now) { if(l>r) { if(mp[sum]==0) mp[sum]=++cnt; p[mp[sum]].push_back(now); return; } dfs1(l+1,r,sum+a[l],now|1<<(l-1)); dfs1(l+1,r,sum-a[l],now|1<<(l-1)); dfs1(l+1,r,sum,now); } void dfs2(int l,int r,int sum,int now) { if(l>r) { int tmp=mp[sum]; if(tmp==0) return; for(int i=0;i<p[tmp].size();i++) ans[now|p[tmp][i]]=1; return; } dfs2(l+1,r,sum+a[l],now|1<<(l-1)); dfs2(l+1,r,sum-a[l],now|1<<(l-1)); dfs2(l+1,r,sum,now); } int main() { // ios::sync_with_stdio(false); cin>>n; //cout<<n<<endl; for(int i=1;i<=n;i++) cin>>a[i];//cout<<a[i]<<endl; dfs1(1,n>>1,0,0); dfs2((n>>1)+1,n,0,0); for(int i=1;i<=(1<<n);i++) res+=ans[i];//ai>=1 cout<<res<<'\n'; return 0; }

 

posted @ 2023-10-28 17:51  JMXZ  阅读(14)  评论(0)    收藏  举报