洛谷P6773 命運

2022-06-13 16:12:07 字數 3744 閱讀 4373

提示:我們在題目描述的最後一段提供了乙份簡要的、形式化描述的題面。

在遙遠的未來,物理學家終於發現了時間和因果的自然規律。即使在乙個人出生前,我們也可以通過理論分析知曉他或她人生的一些資訊,換言之,物理學允許我們從一定程度上「預言」乙個人的「命運」。

簡單來說,乙個人的命運是一棵由時間點構成的有根樹 \(t\):樹的根結點代表著出生,而葉結點代表著死亡。每個非葉結點 \(u\) 都有乙個或多個孩子 \(v_1, v_2,\dots , v_\),表示這個人在 \(u\) 所代表的時間點做出的 \(c_u\) 個不同的選擇可以導向的不同的可能性。形式化的,乙個選擇就是樹上的一條邊 \((u, v_i)\),其中 \(u\) 是 \(v_i\) 的父結點。

乙個人的一生是從出生(即根結點)到死亡(即某乙個葉子結點)的一條不經過重複結點的路徑,這條路徑上任何乙個包含至少一條邊的子路徑都是這個人的一段人生經歷,而他或她以所有可能的方式度過一生,從而擁有的所有人生經歷,都被稱為潛在的人生經歷。換言之,所有潛在的人生經歷就是所有 \(u\) 到 \(v\) 的路徑,滿足 \(u, v \in t\),\(u \neq v\),並且 \(u\) 是 \(v\) 的祖先。在數學上,這樣乙個潛在的人生經歷被記作有序對 \((u, v)\),樹 \(t\) 所有潛在的人生經歷的集合記作 \(\mathcal p_t\)。

物理理論不僅允許我們觀測代表命運的樹,還能讓我們分析一些潛在的人生經歷是否是「重要」的。乙個人所作出的每乙個選擇——即樹上的每一條邊——都可能是重要不重要的。一段潛在的人生經歷被稱為重要的,當且僅當其對應的路徑上存在一條邊是重要的。我們可以觀測到一些潛在的人生經歷是重要的:換言之,我們可以觀測得到乙個集合 \(\mathcal q \subseteq \mathcal p_t\),滿足其中的所有潛在的人生經歷 \((u, v) \in \mathcal q\) 都是重要的。

樹 \(t\) 的形態早已被計算確定,集合 \(\mathcal q\) 也早已被觀測得到,乙個人命運的不確定性已經大大降低了。但不確定性仍然是巨大的——來計算一下吧,對於給定的樹 \(t\) 和集合 \(\mathcal q\),存在多少種不同的方案確定每條邊是否是重要的,使之滿足所觀測到的 \(\mathcal q\) 所對應的限制:即對於任意 \((u, v) \in \mathcal q\),都存在一條 \(u\) 到 \(v\) 路徑上的邊被確定為重要的。

形式化的:給定一棵樹 \(t = (v, e)\) 和點對集合 \(\mathcal q \subseteq v \times v\) ,滿足對於所有 \((u, v) \in \mathcal q\),都有 \(u \neq v\),並且 \(u\) 是 \(v\) 在樹 \(t\) 上的祖先。其中 \(v\) 和 \(e\) 分別代表樹 \(t\) 的結點集和邊集。求有多少個不同的函式 \(f\) : \(e \to \\)(將每條邊 \(e \in e\) 的 \(f(e)\) 值置為 \(0\) 或 \(1\)),滿足對於任何 \((u, v) \in \mathcal q\),都存在 \(u\) 到 \(v\) 路徑上的一條邊 \(e\) 使得 \(f(e) = 1\)。由於答案可能非常大,你只需要輸出結果對 \(998,244,353\)(乙個素數)取模的結果。

假設我們已經確定點 \(x\) 子樹內所有邊的權值,剩餘沒有被 \(1\) 「覆蓋」 且 \(y\in \operatorname\)的點對 \((x,y)\) 中,\(x\) 深度最深的為 \(d\),那麼我們只要知道這個 \(d\) 就惡意進行轉移。

設 \(f[x][i]\) 表示點 \(x\) 的子樹內,沒有被覆蓋的點對中祖先的最大深度為 \(i\) 的方案數。

考慮加入 \(x\) 的乙個兒子 \(y\) 為根的子樹時,分類討論這個 \(i\) 由哪一邊得到的:

\[f[x][i]=f[x][i]\times \sum^_f[y][j]+f[x][i]\times \sum^_ f[y][j]+f[y][i]\times \sum^_ f[x][j]

\]\[f[x][i]=f[x][i]\times (\sum^_f[y][j]+\sum^_ f[y][j])+f[y][i]\times \sum^_ f[x][j]

\]當加入乙個新的約束時,假設這個約束的深度為 \(d\),那麼直接讓 \(f[x][d]=\sum^_f[x][i]\),然後將 \(f[x][d+1\sim dep[x]]\) 全部賦值為 \(0\) 即可。

直接上樹形 dp,時間複雜度 \(o(n^3)\);加上字首和優化即可做到 \(o(n^2)\)。

我們把點 \(x\) 對應的每乙個 dp 值 \(f[x][i]\) 放到一棵線段樹上,那麼將 \(y\) 的線段樹合併到 \(x\) 的線段樹時:

#include using namespace std;

typedef long long ll;

const int n=500010,mod=998244353,lg=40;

int n,m,tot,maxd[n],head[n],dep[n],rt[n];

ll sumx,sumy;

int read()

struct edge

e[n*2];

void add(int from,int to)

void dfs1(int x,int fa)

struct segtree

if (mul[x]>1)

}void pushup(int x)

int update(int x,int l,int r,int p,ll v)

int mid=(l+r)>>1;

if (p<=mid) lc[x]=update(lc[x],l,mid,p,v);

else rc[x]=update(rc[x],mid+1,r,p,v);

pushup(x);

return x; }

ll query(int x,int l,int r,int ql,int qr)

void clear(int x,int l,int r,int ql,int qr)

int mid=(l+r)>>1;

if (qr<=mid) clear(lc[x],l,mid,ql,qr);

else if (ql>mid) clear(rc[x],mid+1,r,ql,qr);

else clear(lc[x],l,mid,ql,mid),clear(rc[x],mid+1,r,mid+1,qr);

pushup(x); }

int merge(int x,int y,int l,int r)

if (y && !x)

if (l==r)

int mid=(l+r)>>1;

lc[x]=merge(lc[x],lc[y],l,mid);

rc[x]=merge(rc[x],rc[y],mid+1,r);

f[x]=(f[lc[x]]+f[rc[x]])%mod;

return x;

}}seg;

void dfs2(int x,int fa)

} if (maxd[x]) }

int main()

dfs1(1,0);

m=read();

for (int i=1,x,y;i<=m;i++)

dfs2(1,0);

printf("%lld\n",seg.query(rt[1],0,n,0,0));

return 0;

}

洛谷P5049 洛谷P5022 題解 旅行

原題 資料加強版 加強版 參考你谷題解 終於調過了 又是一如既往的申必錯誤 noi plus石錘了 原題的資料允許我們 o n 2 暴力斷邊,但是加強版的資料達到了 n log n 級別,我們必須在斷邊這一環節尋求更好的解法。考慮我們進入環後在何處回溯 根據繼續走環走到的點分類 設當前已經從 b 走...

洛谷練習P2279 P1346

2020年,人類在火星上建立了乙個龐大的基地群,總共有n個基地。起初為了節約材料,人類只修建了n 1條道路來連線這些基地,並且每兩個基地都能夠通過道路到達,所以所有的基地形成了乙個巨大的樹狀結構。如果基地a到基地b至少要經過d條道路的話,我們稱基地a到基地b的距離為d。由於火星上非常乾燥,經常引發火...

洛谷 P1396 營救

題目描述 咚咚咚 查水表!原來是查水表來了,現在 找這麼熱心上門的查表員啊!小明感動的熱淚盈眶,開起了門 媽媽下班回家,街坊鄰居說小明被一群陌生人強行押上了警車!媽媽豐富的經驗告訴她小明被帶到了t區,而自己在s區。該市有m條大道連線n個區,一條大道將兩個區相連線,每個大道有乙個擁擠度。小明的媽媽雖然...