題意:有n個數,除了空集外,它們會造成2^n-1個子集,給你這些子集的和的結果,讓你還原原來的n個數。c++
假設原數是3 5 16,spa
那麼它們造成3 5 8 16 19 21 24,指針
那麼第一輪取出開頭的數(3),而後從當前最大的數(24)中減去它,而後必然會產生一個與其相等的數(21),將其一併刪去(這個過程利用單調性,使用兩個指針進行單調的從右向左的移動便可),而後將21進入下一輪的末尾……如此,3就是答案裏的數。blog
下一輪變成 5 16 21……如此重複,每次序列長度減半,獲得最終答案。get
隊友的代碼:it
#include <bits/stdc++.h> using namespace std; #define FOR(i,a,b) for (int i=(a);i<=(b);++i) #define ROF(i,b,a) for (int i=(b);i>=(a);--i) typedef long long LL; int read(){ int x=0,f=1; char ch=getchar(); while (ch<'0'||ch>'9') { if (ch=='-') f=-1; ch=getchar(); } while (ch>='0'&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); } return x*f; } const int MAXN=3000006; queue<int> Q; int n,m,q,a[MAXN],b[MAXN],c[MAXN]; void dfs(int x,int y){ if (x==n+1) { if (y) c[++q]=y; return; } dfs(x+1,y); dfs(x+1,y+b[x]); } int main() { int T=read(); while (T--) { n=read(); m=(1<<n); FOR(i,1,m-1) a[i]=read(); sort(a+1,a+m); while (!Q.empty()) Q.pop(); int flag=1; FOR(i,1,n) { b[i]=a[1]; q=0; int x=0,y=a[1]; ROF(j,m-1,2) { if (!x) if (!Q.empty()) x=Q.front(); else x=0; if (a[j]==x) c[++q]=a[j],Q.pop(),x=0; else Q.push(a[j]-y); } //FOR(j,1,q) printf("%d%c",c[j]," \n"[j==q]); //printf("%d %d %d\n",Q.empty(),m/2-1,q); if (!Q.empty()||q!=m/2-1) { flag=0; break; } FOR(j,1,q) a[q+1-j]=c[j]; m>>=1; } if (flag) FOR(i,1,n) printf("%d%c",b[i]," \n"[i==n]); else printf("NO\n"); } return 0; } /* */