这题训练赛时没搞出来,我当时从正面考虑,发现会有很多种情况
看了PKKJ的wiki  发现从反面考虑很好!!

/*
    题意:一个n个点的图,任意两点间有边的概率为p  问该图连通的概率
    设n个点连通的概率为dp[n],从不连通来考虑,_dp[n]=1-dp[n]

    对于编号为1的点,它在其中的一个连通块,枚举该块的大小 1n-1
    则该块的k条边必须与其余点的(n-k)条边都不能连通
              n-1
    则_dp[n] = ∑ C[n-1,k-1]*dp[k]*(1-p)^(k*(n-k))
              k=1
    则dp[n]=1-_dp[n]

    最初,我是考虑最后怎么连通的情况,即点n是如何与其他块连起来的,发现情况复杂:
    点n与大小为n-1的一个连通块连起来
    点n作为中间点连接两个块
    点n作为中间点连接三个块
    
    其实这样子,就应该要想到从反面来考虑!!考虑不连通
    要不连通,只需考虑某一个特殊的块被独立开来,而其他块不管他连不连通
*/

#include
<cstdio>
#include
<cmath>

double dp[30];
int C[30][30];

void init()
{
    
for(int i=0;i<30;i++)
        C[i][
0]=C[i][i]=1;
    
for(int i=2;i<30;i++)
        
for(int j=1;j<i;j++)
            C[i][j]
=C[i-1][j]+C[i-1][j-1];
}


int main()
{
    init();
    
int n;
    
double p;
    
while(~scanf("%d%lf",&n,&p))
    
{
        dp[
1]=1.0;
        
//_dp[n] = ∑C[n-1,k-1]*dp[k]*(1-p)^(k*(n-k))
        
//dp[n]=1-_dp[n];
        for(int nn=2;nn<=n;nn++)
        
{
            
double ans = 0.0;
            
for(int k=1;k<nn;k++)
                ans
+=C[nn-1][k-1]*dp[k]*pow(1-p,k*(nn-k)+0.0);
            dp[nn]
=1-ans;
        }

        printf(
"%.8f\n",dp[n]);
    }

    
return 0;
}