思路借鉴:收集卡牌
看到只有16张牌,想到状压dp
f[i][j]表示抽到卡牌状态为i,已经抽了j次,此时的概率
注意:最后输出的时候要输出10位小数,否则会0分。
#include <bits/stdc++.h>
using namespace std;
double f[1<<20][120];//抽到卡牌为i,已经抽了j次,此时的概率
double p[20];
int cnt[1<<20];
int main(){
int n,k;
cin>>n>>k;
for(int i=0;i<n;i++){
cin>>p[i];
}
f[0][0]=1.0;
double ans=0.0;
for(int i=0;i<=(1<<n);i++){
int x=i;
while(x){
cnt[i]+=x%2;
x/=2;
}
}
for(int i=0;i<=(1<<n);i++){
for(int j=0;j<=100;j++){
if(cnt[i]+(j-cnt[i])/k==n){
ans+=j*f[i][j];
continue;
}
for(int k=0;k<n;k++){
if(i&(1<<k)) f[i][j+1]+=p[k]*f[i][j];
else f[i|(1<<k)][j+1]+=p[k]*f[i][j];
}
}
}
printf("%.10lf",ans);
}