link:死亡之樹
關於去重 還是有講究的。
題目求本質不同的 具有k個葉子節點的樹的個數 不能上矩陣樹。
點數很少容易想到裝壓dp 考慮如何刻畫樹的形狀 發現乙個維度做不了 所以。
設狀態 f[i][j]表示 點的集合為i葉子集合的點為j的方案樹。
這樣我們就能知道這棵樹大致的樣子 空間 為\(2^\)
當然 如果使用三進製狀壓 空間複雜度還會進一步降到3^n 不過這道題沒有卡空間。
考慮轉移 可以列舉點 也可以列舉邊。
先考慮列舉邊 會出現重複的情況 如先加這條邊再加那條邊 兩條邊可以交換。
考慮強制按順序的話 需要記上次加入的邊是什麼。時間上過不了。
考慮最後除以(n-1)! 這樣也不行因為 這樣的話 每次考慮加入邊的時候點的狀態的刻畫存在問題。
考慮列舉點 此時實質還是在加邊 還是有重複的。
甚至在某個時刻都有可能出現順序帶來方案數不同的問題。
還是考慮點的有序性 考慮 從乙個狀態到達另外乙個狀態轉移的唯一性。
可以發現在列舉決策的時候 只有當前決策大於葉子節點的最大的那個再進行轉移 此時這樣就保證了每一種樹都是以唯一的方式構造出來的。
證明 倒著想 考慮當前的一棵樹的上乙個狀態 一定是當前狀態減掉最大編號的葉子節點得到的 如果不是 那麼上個狀態是不能轉移到當前狀態的。
歸納一下可以得證。
const ll maxn=11;
ll n,maxx,m,k;
ll sum[1<>1]+(i&1);
rep(1,maxx,i)
}} }
ll ans=0;
for(ll j=maxx;j;j=maxx&(j-1))if(sum[j]==k)ans+=f[maxx][j];
putl(ans);return 0;
}
一本通 高手訓練 遊戲通關
遊戲通關 xy在玩乙個包含n n 個任務的遊戲。每個任務完成時限為t i ti 你可以認為還沒開始做任務時的時間為0 0 獎勵為w i wi 由於xy技術的嫻熟以及任務的簡單,對於每個任務,他都可以在乙個單位時間內完成。xy想要知道他能夠獲得的最多的獎勵。第一行乙個整數n n,表示需要完成的任務數目...
一本通 高手訓練 撲克牌
一副撲克牌有n n張牌。一般你買的一副新撲克牌裡除了這n n張牌外還會有一些張特殊的牌,如果你不小心弄丟了n n張牌中的某一張,就可以用特殊牌來代替,但是如果你弄丟兩張的話就沒有辦法了,因為特殊牌上的圖案是一樣的。現在你得到了很多撲克牌,準確來說,n n n種牌你各有a1,a2,an a1,a2,a...
一本通 Trie字典樹
phone list includeusing namespace std const int n 1e5 5 int t,n,tot,c n 10 char s 10 bool ans,bo n void clear bool insert bo u 1 return flag int main ...