这又是什么毒瘤.....
解:把操作序列倒着来,就是考虑前k个入队的元素了。显然这样每个元素的概率不变。
状压。设fs表示当前元素为s的概率。
每次转移的时候选择一个不在s中的元素,作为下一个加入的元素。注意实际上有可能选择到在s中的元素。
然后我们设选择到s中元素的概率为x。
我们可能第一次就选到i,也有可能第2次选到,第3次选到......
概率分别是pi,x * pi,x2 * pi,......
无限求和有pi / (1 - x)。
所以最后转移的时候就是fs * pi * / (1 - x)
记得判断有用元素不足k的时候直接输出。
1 #include <bits/stdc++.h> 2 3 const int N = 25, M = 1200010; 4 5 double p[N], f[M], ans[N], P[M]; 6 int n, k, wp[M], cnt[M]; 7 8 inline void out(int x) { 9 for(int i = n - 1; i >= 0; i--) printf("%d", (x >> i) & 1); 10 puts(""); 11 return; 12 } 13 14 int main() { 15 int Cnt = 0; 16 scanf("%d%d", &n, &k); 17 for(int i = 0; i < n; i++) { 18 scanf("%lf", &p[i]); 19 if(p[i] > 0) Cnt++; 20 } 21 if(Cnt < k) { 22 for(int i = 0; i < n; i++) { 23 if(p[i] > 0) printf("1 "); 24 else printf("0 "); 25 } 26 return 0; 27 } 28 29 30 int lm = (1 << n); 31 for(int i = 0; i < n; i++) wp[1 << i] = i; 32 for(int i = 1; i < lm; i++) { 33 cnt[i] = 1 + cnt[i - (i & (-i))]; 34 P[i] = P[i - (i & (-i))] + p[wp[i & (-i)]]; 35 } 36 f[0] = 1; 37 for(int i = 0; i < lm; i++) { 38 //out(i); 39 if(cnt[i] == k) { 40 for(int s = 0; s < n; s++) { 41 if(i & (1 << s)) { 42 ans[s] += f[i]; 43 } 44 } 45 continue; 46 } 47 if(cnt[i] > k) continue; 48 for(int s = 0; s < n; s++) { 49 if((i >> s) & 1) continue; 50 f[i | (1 << s)] += f[i] * p[s] / (1 - P[i]); 51 } 52 } 53 54 for(int i = 0; i < n; i++) printf("%.8f ", ans[i]); 55 return 0; 56 }