我真是服了这个数学期望了,打卡代码里满满debug的痕迹(4009.收集卡牌)
#include <iostream>
#include <cstring>
using namespace std;
const int N = 16, M = 1 << N;
int n, K;
double p[N];
double f[M][N * 5 + 1]; //表示卡牌的数量,抽了多少次
int G[M];
//int rrr;
//int aaa, ttt;
int get(int x)
{
//aaa++;
if (G[x] != -1) return G[x];
int res = 0;
//ttt++;
int o = x;
while (x)
{
//rrr++;
res++;
x -= x & -x;
}
G[o] = res;
return res;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
memset(G, -1, sizeof G);
cin >> n >> K;
for (int i = 0; i < n; i++) cin >> p[i];
f[0][0] = 1;
double res = 0;
for (int i = 1; i < 1 << n; i++)
{
for (int j = get(i); j <= n * K; j++)
{
for (int k = 0; k < n; k++)
{
//rrr++;
if (i >> k & 1)
{
if (i + 1 != 1 << n &&
(n - get(i)) * K > j - 1 - get(i))
f[i][j] += f[i][j - 1] * p[k];
if ((n - get(i - (1 << k))) * K > j - 1 - get(i - (1 << k)))
f[i][j] += f[i - (1 << k)][j - 1] * p[k];
}
}
if (i + 1 == 1 << n || (n - get(i)) * K <= j - get(i))
{
//rrr++;
//if (f[i][j])cout << i << ' ' << j << ' ' << f[i][j] << endl;
res += j * f[i][j];
}
//cout << f[i][j] << ' ';
}
//cout << endl;
}
//cout << aaa << ' ' << ttt << ' ' << rrr << endl;
cout << res << endl;
}