牛客網 Wannafly挑戰賽27 藍魔法師

2022-04-30 02:42:09 字數 1333 閱讀 1907

「你,你認錯人了。我真的,真的不是食人魔。」--藍魔法師

給出一棵樹,求有多少種刪邊方案,使得刪後的圖每個連通塊大小小於等於\(k\),兩種方案不同當且僅當存在一條邊在乙個方案中被刪除,而在另乙個方案中未被刪除,答案對\(998244353\)取模

第一行兩個整數\(n\),\(k\), 表示點數和限制

\(2 \le n \le 2000, 1 \le k \le 2000\)

接下來\(n-1\)行,每行包括兩個整數\(u\),\(v\),表示\(u\),\(v\)兩點之間有一條無向邊

共一行,乙個整數表示方案數對\(998244353\)取模的結果

長見識了,比賽交了\(8\)次最後終於過了。

樹上分組揹包,令\(dp_\)代表子樹\(i\)還剩餘\(j\)個點可以連出去時的方案數。

這個轉移每個人的寫法都可以不一樣,說一下我的。

初始化\(dp_=1\),代表先強制選\(i\)

對每個子樹做\(dp_=dp_\times dp_\)表示連線

特判直接砍掉子樹的情況,在做子樹之前\(dp_=dp_\times dp_\)

做完後再處理一下自己被砍的情況。

注意倒序列舉。

這樣寫出來是這樣的。

void dfs(int now,int fa)

}for(int i=1;i<=min(k,siz[now]);i++) (dp[now][0]+=dp[now][i])%=mod;

}

很不幸的是這樣寫可以輕鬆被鏈卡到\(o(n^3)\)

有一種寫法是\(o(n^2)\)的

先枚舉子樹大小那麼大,然後更新當前樹

void dfs(int now,int fa)

int rr=min(k,siz[now]);

for(int i=1;i<=rr;i++) (dp[now][0]+=dp[now][i])%=mod;

}

值得一提的是,這個跑法的複雜度是非常嚴格的,隨機資料下進入核心轉移的地方只有\(\frac\)次,怎麼構造都是這樣(當然按不考慮\(k\)的大小的剪枝)

為什麼呢?考慮一種感性的理解方式。

每一對點,當且僅當在它們的\(\tt\)時,能夠被轉移。

考慮修補一下第一種做法,發現多餘的轉移是因為權值為\(0\),如果我們這樣寫,那麼複雜度也是一樣的了

void dfs(int now,int fa)

}for(int i=1;i<=k;i++) (dp[now][0]+=dp[now][i])%=mod;

}

2018.10.27

牛客網 Wannafly挑戰賽21 A 燈塔

題目鏈結 題目描述 z市是一座港口城市,來來往往的船隻依靠燈塔指引方向。在海平面上,存在n個燈塔。每個燈塔可以照亮以它的中心點為中心的90 範圍。特別地,由於特殊限制,每個燈塔照亮範圍的角的兩條邊必須要麼與座標軸平行要麼與座標軸成45 由於經費限制,z市的燈塔只能被點亮一座。你需要求出在這種情況下,...

牛客Wannafly挑戰賽12 題解

傳送門 說是比賽題解,其實我只會前三題 後面的一定補 t1題意,在乙個長度為n的時間內,問如何選擇存款期限,使得收益最大。dp include include include include using namespace std define fi first define se second d...

牛客網wannafly挑戰賽13 D 貪心

時間限制 c c 1秒,其他語言2秒 空間限制 c c 262144k,其他語言524288k 64bit io format lld 第一行包括兩個數t,n,表示有n個蛋糕,最小的蛋糕的質量與最大的蛋糕的質量的比值不小於t 接下來n行,每行乙個數wi,表示n個蛋糕的質量輸出包括一行,為最小切割的刀...