解題思路
考場上想出了外向樹的做法,居然沒意識到反向邊可以容斥,其實外向樹會做的話這個題差不多就做完了。
令 \(dp[u][i]\) 表示單獨考慮 \(u\) 節點所在子樹,子樹內 \(\sum w=i\) 的合法概率,可以簡單證明子樹外的選取是不影響子樹內的答案的,所以可以這樣表示。
證明:我們只考慮子樹內的第乙個選出根節點 \(u\) 的概率是 \(\frac\),假設當前未被選走的卡的概率之和為 \(s\) ,那麼考慮全部未被選走的卡,子樹內第乙個選走 \(u\) 的概率為
\[\dfrac\sum_^ (\dfrac)^k
=\dfrac\times\dfrac} \\
=\dfrac \times \frac= \frac
\]兩式相等,得證。
轉移比較顯然,因為是外向樹,所以 \(u\) 要當中第乙個被選中,剩下相當於對 \(w\) 做揹包,直接從兒子合併即可。
考慮不是一棵外向樹對其進行容斥,令 \(g(k)\) 表示有 \(k\) 條反向邊被欽點為正向,剩下的反向邊可反向也可正向的方案數,那麼答案就是 \(\sum_^m (-1)^i g(i)\) 。
發現可反向也可正向相當於把這條邊刪掉,兩個連通塊貢獻用乘法原理合併,然後把容斥係數帶到 \(dp\) 轉移裡面計算即可。
code
/*program by mangoyang*/
#include #define inf (0x7f7f7f7f)
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
typedef long long ll;
using namespace std;
template inline void read(t &x)
const int mod = 998244353;
vectorg[1005], d[1005];
int dp[1005][3005], sz[1005], w[1005][4], a[3005], n;
inline void up(int &x, int y)
inline int pow(int a, int b)
inline void gao(int u, int v, int type)
for(int i = 1; i <= 3 * (sz[u] + sz[v]); i++)
dp[u][i] = a[i], a[i] = 0;
sz[u] += sz[v];
}inline void dfs(int u, int fa)
int main()
for(int i = 1, x, y; i < n; i++)
dfs(1, 0);
int ans = 0;
for(int i = 1; i <= 3 * n; i++) up(ans, dp[1][i]);
cout << ans << endl;
return 0;
}
p5405 CTS2019 氪金手遊
題目大意 題意狗屁不通 看毛子語都比看這個題面強 分析 我們假設這棵樹是乙個內向樹 那麼我們可以輕易的得到dp x i 表示x點子樹和為i的期望 轉移只需列舉當前期望大小和子樹期望大小即可 但是由於邊的方向不一定 所以這棵樹上存在反向邊 我們可以容斥有i個邊不合法的情況 因此對於乙個反向邊要麼x點加...
loj 3124 CTS2019 氪金手遊
n 種卡,每種有權值 w i w i 以 p 的概率取 j j 1,2,3 不斷抽卡,抽到卡 i 的概率是 frac n w j 設 t i 表示第一次抽到 i 的時間 給定 n 1 個限制 u i,v i 要求 t 以所有限制做邊可形成一棵 n 個節點的樹 求滿足所有限制的概率 n leq 10 ...
P5405 CTS2019 氪金手遊
這應該是cts2019最簡單的題。lhm 首先假設題目給的是乙個單向的鏈,並且所有 w 都是確定的,那麼顯然第一步一定要選擇鏈的起點,概率為 frac 第二步如果選到起點,就再選一次,因此相當於與起點無關,因此合法概率為 frac 第三步合法概率為 frac 如果給的是乙個外向樹,我們發現兒子與兒子...