原題連接html
有一天,蒜頭君當上了國王。蒜頭君的王國有 n n n 坐城市,如今他須要在城市之間修建道路使得城市之間相互聯通。
蒜頭君是一個不會規劃的人,他不知道哪些城市之間必需要有道路,因此對於任意兩座城市之間,蒜頭軍會修建道路的機率爲 p p p。
請你計算一下最後修建出來的道路使得 n n n 座城市都聯通的機率。ios輸入格式
輸入包含一個整數 n ( 1 ≤ n ≤ 20 ) n(1≤n≤20) n(1≤n≤20) 和一個實數 p ( 0 ≤ p ≤ 1 ) p(0≤p≤1) p(0≤p≤1).web
輸出格式
輸出一行一個實數表示答案,輸出結果偏差在 1 0 − 5 10^{−5} 10−5 之內都認爲正確。svg
輸入樣例
3 0.6輸出樣例
0.6480000
參考大佬的題解
題目讓求 n n n個點都聯通的機率 F ( n ) F(n) F(n)。不妨先求一下 n n n個點組成的圖不連通的機率 G ( n ) G(n) G(n)
考慮n個點組成的圖不連通有如下 n − 1 n-1 n−1中狀況:
1 1 1個點連通, 且這 1 1 1個點組成的連通塊, 與其他 n − 1 n-1 n−1個點沒有邊相連
2 2 2個點連通, 且這 2 2 2個點組成的連通塊, 與其他 n − 2 n-2 n−2個點沒有邊相連
…
k k k個點連通, 且這 k k k個點組成的連通塊, 與其他 n − k n-k n−k個點沒有邊相連
…
n − 1 n-1 n−1個點連通, 且這 n − 1 n-1 n−1個點組成的連通塊, 與剩餘的 1 1 1個點沒有邊相連
考慮有 k k k個點連通的狀況:
首先要選 k k k個點, 而第 n n n個點必定選,則再從 n − 1 n-1 n−1個點中選擇 k − 1 k-1 k−1個, 即 C n − 1 k − 1 C_{n-1}^{k-1} Cn−1k−1
而後保證這 k k k個點連通, 即 F ( k ) F(k) F(k)
最後保證這 k k k的點與其他 n − k n-k n−k個點沒有邊相連, 即 ( 1 − p ) k ( n − k ) (1-p)^{k(n-k)} (1−p)k(n−k) ( p p p爲兩點間修路的機率)
從而根據上述 n − 1 n-1 n−1種狀況求出 G ( n ) G(n) G(n), 則 題目所求 F ( n ) = 1 − G ( n ) F(n) = 1-G(n) F(n)=1−G(n)spa
#include <cstdio> #include <iostream> #include <cmath> using namespace std; const int N = 29; int n; double p; double f[N]; // f[i]表示n個點都聯通的機率 int c(int a, int b) // 計算組合數 C(a,b), 即從a個點中選b個點 { int sum = 1; for(int i=1; i<=b; i++) sum = sum*(a-b+i)/i; return sum; } int main() { cin >> n >> p; f[1] = 1, f[2] = p; // 易知: 1個點聯通的機率爲1, 2個點聯通機率爲p; for(int i=3; i<=n; i++) { double fail = 0; // 表示i個點不聯通的機率 for(int j=1; j<=i-1; j++) { fail += ( c(i-1, j-1)*f[j]*pow(1.0-p,j*(i-j)) ); } f[i] = 1.0-fail; } printf("%.7lf",f[n]); return 0; }