ADPC2-G 希望
希望
題意:
有A,B兩棵樹,對于一個1到n的全排列a[i],讓樹A中的點i和樹B的節點a[i]連一條邊,希望指數:兩棵樹和新加入的邊構成的圖中,環長為m的環的個數。數組a[]可以任意交換位置,且任意,隨機,不限次數的交換。計算出期望情況下,兩棵樹的希望指數
n≤300,3≤m≤7
題解:
期望=概率 * 對應的權值
在本題中概率肯定是1n!\frac{1}{n!}n!1?,因此需要求所有情況下環長為m的環的個數
我們開始找環的分布情況,一定是左側的點和右側的點通過之間加的點形成環,如圖,圖中環長為6
且所有環用到中間新建邊只能為兩條邊,可能會疑惑,為什么?像圖中情況,用到的新建邊的數量為4,不是2,但是圖中環的長度為8(這已經是新建邊4所對應的環最小長度),而題目保證所求環長<=7,剛好不行。也就是其實題目是隱含著新建邊最多用兩條,不可能更多
我們確定了中間邊只能用2,那就好說了,比如讓你求環為x的數量,x先減2,y=x-2,然后就是兩個樹一共構成長度為y,因此我們預先處理出兩個子樹分別能組成長度為len的邊的數量,用桶來存。比如:tong1[i]:表示在樹A中長度為i的邊的數量。那么答案就:tong1[i]?tong2[m?i?2]?2.0?((n?2))tong1[i]*tong2[m-i-2]*2.0*((n-2))tong1[i]?tong2[m?i?2]?2.0?((n?2))
i是樹A需要提供的邊,m-i-2是樹B需要提供的邊,乘2.0是因為邊可以交叉和不交叉來,正好兩種,而最后(n-2)!是什么?我們之前說過最多用新增邊為2,那么說明左右各有兩個點要被占用(因為一個邊有兩個點),而其他的點可以任意排列,剩下的點就是(n-2)個,任意排列就是階乘
再講一些細節:
比如樹上所有路徑長度,可以用floyd來求,因為答案要乘(n-2)!,而最終答案還要除以n!,所以直接除以n*(n-1)即可
代碼:
#include <bits/stdc++.h> #include <unordered_map> #define debug(a, b) printf("%s = %d\n", a, b); using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> PII; clock_t startTime, endTime; //Fe~Jozky const ll INF_ll= 1e18; const int INF_int= 0x3f3f3f3f; void read(){}; template <typename _Tp, typename... _Tps> void read(_Tp& x, _Tps&... Ar) {x= 0;char c= getchar();bool flag= 0;while (c < '0' || c > '9')flag|= (c == '-'), c= getchar();while (c >= '0' && c <= '9')x= (x << 3) + (x << 1) + (c ^ 48), c= getchar();if (flag)x= -x;read(Ar...); } template <typename T> inline void write(T x) {if (x < 0) {x= ~(x - 1);putchar('-');}if (x > 9)write(x / 10);putchar(x % 10 + '0'); } void rd_test() { #ifdef ONLINE_JUDGE #elsestartTime = clock ();freopen("data.in", "r", stdin); #endif } void Time_test() { #ifdef ONLINE_JUDGE #elseendTime= clock();printf("\nRun Time:%lfs\n", (double)(endTime - startTime) / CLOCKS_PER_SEC); #endif } const int maxn=400; vector<int>a[maxn],b[maxn],g[maxn]; int L[maxn]; int x[maxn][maxn]; int y[maxn][maxn]; int tong1[maxn],tong2[maxn]; int main() {//rd_test();int n,m;cin>>n>>m;for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){x[i][j]=1e9;y[i][j]=1e9;}}for(int i=1;i<n;i++){int u,v;read(u,v);x[u][v]=x[v][u]=1;}for(int i=1;i<n;i++){int u,v;read(u,v);y[u][v]=y[v][u]=1;}for(int k=1;k<=n;k++){for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){x[i][j]=min(x[i][j],x[i][k]+x[k][j]);y[i][j]=min(y[i][j],y[i][k]+y[k][j]);}}}for(int i=1;i<=n;i++){for(int j=i+1;j<=n;j++){if(i==j)continue;if(x[i][j]==1e9)continue;if(y[i][j]==1e9)continue;tong1[x[i][j]]++;tong2[y[i][j]]++;}}double ans=0;for(int i=1;i<=m-3;i++){ans=ans+1.0*tong1[i]*tong2[m-i-2]*2.0/(1.0*n*(n-1));}printf("%.4lf\n",ans);//Time_test(); }總結
以上是生活随笔為你收集整理的ADPC2-G 希望的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: F.孤独(牛客小白月赛39)
- 下一篇: windows错误恢复(或系统崩盘),教