http://acm.hdu.edu.cn/showproblem.php?pid=6092
题意:
给出两个数组A和B,A数组一共可以有(1<<n)种不同的集合组合,B中则记录了每个数出现的次数,现在要根据B数组来推出A数组最小的序列。
思路:
如果$B_{i}$是 B 数组中除了$B_{0}$ 以外第一个值不为 0 的位置,那么显然 i 就是 A 中的最小数。
那么我们每次取出$B_{i}$一个数,对于后面的数组来说,满足$B_{j}=B_{j}-B_{j-i}$,为什么?
其实仔细想想就可以了,比如现在取出的i为2,那么$B_{5}$的方案数是不是可以通过$B_{3}$加上2来合成,所以这也就是上面的式子了。
1 #pragma comment(linker, "/STACK:102400000,102400000") 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cstdio> 6 #include<sstream> 7 #include<vector> 8 #include<stack> 9 #include<queue> 10 #include<cmath> 11 #include<map> 12 #include<set> 13 using namespace std; 14 typedef long long ll; 15 typedef pair<int,ll> pll; 16 const int INF = 0x3f3f3f3f; 17 const int maxn=1e4+5; 18 19 int n, m; 20 ll a[60]; 21 ll b[maxn]; 22 23 int main() 24 { 25 //freopen("in.txt","r",stdin); 26 int T; 27 scanf("%d",&T); 28 while(T--) 29 { 30 int cnt=0; 31 scanf("%d%d",&n,&m); 32 for(int i=0;i<=m;i++) scanf("%I64d",&b[i]); 33 for(int i=1;i<=m;i++) 34 { 35 if(b[i]) 36 { 37 a[++cnt]=i; 38 for(int j=i;j<=m;j++) 39 { 40 b[j]-=b[j-i]; 41 } 42 i--; 43 } 44 } 45 for(int i=1;i<=cnt;i++) 46 { 47 printf("%d",a[i]); 48 if(i!=cnt) printf(" "); 49 else printf(" "); 50 } 51 } 52 return 0; 53 }