吐槽
我终于听懂期望了!!!
期望
这个的概念就不多说了,前面已经说过了,下面就全是题目。
要求的就是E[S],下面就是推导
Xi表示当前有i−1个数,E[S]=E[∑Xi]=∑E[Xi]
成功匹配的概率为(n−i+1)/n,所以E[Xi]=n/(n−i+1)
E[S]=∑E[Xi]=∑n/i
感性理解,a要么在b前面,要么在b后面,所以是1/2
首先,我们可以把联通块的个数变成点的个数-边的个数
那么E(答案)=E(点数)-E(边数)=1/P(点数)-1/P(边数)=∑1/(1/pi)-∑∑1/(1/pi*1/pj)
接下来就直接讲题目吧
这是一道很经典的期望DP设f[S],表示已经集齐了状态为S的卡片期望
f[S]=f[S]*∑pi+f[S-(1<<i)]*pi(i∈S)
f[S]*(1-∑pi)=f[S-(1<<i)]*pi/(1-∑pi)(i∈S)
f[S]=f[S-(1<<i)]*pi/((1-∑pi)*(1-∑pi))(i∈S)
代码如下
#include<bits/stdc++.h>
using namespace std;
const int N=30;
int n;double P,f[1<<21],p[N];
int main()
{
while(~scanf("%d",&n))
{
for(int i=1;i<=n;i++)
scanf("%lf",&p[i]),P+=p[i];
int sum=(1<<n)-1;P=1-P;
for(int S=1;S<=sum;S++)
{
double num=0,ans=1;
for(int j=0;j<n;j++)
{
int now=1<<j;
if(S&now)num+=p[j+1],ans+=p[j+1]*f[S-now];
}
f[S]=ans/num;
}
printf("%.5lf\n",f[sum]);P=0;
}
return 0;
}
每一次操作有4种情况,第一个桶拿出的是未染色,第二个染色。第一个染色,第二个未染色。都未染色或者都染色
用f[i][j]表示第一个桶有i个染色了,第二个桶有j个染色了,将全部染色需要的操作数
显然有f[i][j] = (n-i)*j*f[i+1][j]+(n-j)*i*f[i][j+1]+(n-i)*(n-j)*f[i+1][j+1]+i*j*f[i][j]+1;(对应上面4种可能)
移项即可得f[i][j]*(1-i*j)=(n-i)*j*f[i+1][j]+(n-j)*i*f[i][j+1]+(n-i)*(n-j)*f[i+1][j+1]+1
f[i][j]*(1-i*j)=((n-i)*j*f[i+1][j]+(n-j)*i*f[i][j+1]+(n-i)*(n-j)*f[i+1][j+1]+1)/(1-i*j)
代码如下
#include<iostream>
#include<cstdio>
using namespace std;
#define D double
const int N=1010;
int n,m;D f[N][N];
int main()
{
while(~scanf("%d%d",&n,&m))
{
f[n][m]=0;
for(int i=n;i>=0;i--)
for(int j=i==n?m-1:m;j>=0;j--)
f[i][j]=((D)(n-i)*j*f[i+1][j]+(D)(m-j)*i*f[i][j+1]+(D)(n-i)*(m-j)*f[i+1][j+1]+n*m)/(D)(n*m-i*j);
printf("%.4lf\n",f[0][0]);
}
return 0;
}