這題訓練賽時沒搞出來,我當時從正面考慮,發現會有很多種情況
看了PKKJ的wiki 發現從反面考慮很好!!

/**//*
題意:一個n個點的圖,任意兩點間有邊的概率為p 問該圖連通的概率
設n個點連通的概率為dp[n],從不連通來考慮,_dp[n]=1-dp[n]
對于編號為1的點,它在其中的一個連通塊,枚舉該塊的大小 1
n-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;
}

