分 類 大 討 論給定一棵 \(n\) 個點的樹,將其複製 \(m\) 次得到 \(m+1\) 棵樹,依次編號為 \(0\sim m\)。記編號為 \(i\) 的樹的節點 \(j\) 為 \((i,j)\)。
令所有 \(m+1\) 棵樹上的邊都是雙向邊,另外對於每個 \(i\in[1,m]\),指定 \(a_i,b_i\),連一條有向邊:\((i-1,a_i)\to(i,b_i)\)。這樣得到乙個連通的圖。
兩個玩家 p,q 在這個圖上玩遊戲:最初 \((0,1)\) 上有乙個棋子,每個玩家輪流操作,將棋子挪到相鄰的點上。規定不能挪到已經到過的點,無法繼續移動的玩家輸掉遊戲。
p 為先手,求有多少種 \(a_1,b_1,a_2,b_2,\dots,a_m,b_m\) 的方案使得 p 必勝。
資料規模:\(1\le n\le10^5,1\le m\le10^\)。
可以看出,從樹 \(i-1\) 經過有向邊到達樹 \(i\) 的點 \(b_i\),就可以看成「把 \(b_i\) 作為第 \(i\) 棵樹的根,只能向子樹方向走或走有向邊」這種問題。
走有向邊比較複雜,先不考慮。我們先嘗試求出以點 \(1\) 為根,只能向子樹方向走,每個點是必勝還是必敗;然後通過換根 dp 可以得到每個點為根的答案。
我們可以非常輕鬆地做乙個 dp,求出從點 \(i\) 出發只能朝子樹方向走,先手是否必勝,記為 \(h_i\)(\(h_i=0\) 即必敗,\(h_i=1\) 即必勝)。根據基礎的博弈論知識,當 \(u\) 能轉移到的所有 \(h_v\) 都為 \(1\),則 \(h_u=0\);只要有乙個 \(h_v=0\),則 \(h_u=1\)。
然後考慮加上有向邊 \((i,s)\to (i+1,t)\)。這相當於給 \(s\) 新增了一種轉移方案,不妨討論一下這個新增的轉移會對 \(h_s\) 造成什麼影響:
若 \(t\) 是必勝點:
於是我們再定義乙個 \(g_\),表示 \(u\) 的子樹內有一條連向下一棵樹的有向邊,加上這條有向邊後,\(u\) 的狀態為 \(0\)(必敗)/ \(1\)(必勝)的方案數。
雖然在計算下一棵樹的答案之前,我們無法求出 \(g_\) 的具體值,但是根據之前的討論,我們知道 \(g\) 的值只與「下一棵樹在每個連邊狀態下,必敗點的數量的總和/必勝點的數量的總和」有關,因為只有這兩個值決定了 \(t\) 可取的方案數。
不妨記 \(t_,t_\) 分別表示第 \(i\) 棵樹在所有狀態下必敗點/必勝點數量的總和。那麼 \(g_\) 可以表示為:
\[g_=g_t_+g_t_
\]因為一棵樹只會連出一條有向邊,所以所有的 \(g_\) 都會是這個形式——我們可以 dp 計算出每個係數 \(g_\)。
這只是以 \(1\) 為根的情況,我們仍然可以換根求出「以每個點為根,要使根為必勝/必敗有多少種方案」,記作 \(f_\)。和 \(g\) 一樣,\(f\) 也是關於 \(t_,t_\) 的式子。
然後我們可以得到:
\[\begin
t_&=\sum_^nf_=at_+bt_\\
t_&=\sum_^nf_=ct_+dt_
\end
\]不難發現,對於每棵樹,係數 \(a,b,c,d\) 是相同的(每棵樹的樹形是一樣的,那麼上述dp的轉移也都是一樣的,不一樣的是 \(t_,t_\),但這和係數無關)。
即:\[\begint_\\t_\end
=\begina&b\\c&d\end
\times\begint_\\t_\end
\]計算的終點在第 \(m\) 棵樹,因為它沒有連出的有向邊,可以直接計算出 \(t_,t_\)。
然後這個式子就可以矩陣加速,最終複雜度 \(\mathcal(n+\log m)\)。
唯一的麻煩點在於 \(g\) 的換根 dp。要選擇乙個子樹 \(v\)(或者 \(u\) 本身)連出一條有向邊,則需要考慮除去子樹 \(v\),剩下的子樹中是否有必敗態,若有必敗態,則 \(u\) 一定是必勝態,與 \(v\) 無關;否則 \(u\) 的狀態取決於 \(v\) 連邊後的狀態。
的確有優美的實現方法,但是我考場上嘗試少寫點**結果調到結束都還沒過大樣例……還不如直接分類大討論……
不建議借鑑這份** (;′⌒`)
點選展開/摺疊**
開幕雷擊[doge]
/*lucky_glass*/
#include#include#includeusing namespace std;
templateinline t rin(t &r)
inline int sub(con(int)a,con(int)b)
inline int mul(con(int)a,con(int)b)
inline int ina_pow(con(int)a,con(int)b)
inline int inv(con(int)key)
struct graph
inline int operator (con(int)u)
}gr;
struct data
data(con(int)_sum0,con(int)_sum1):sum0(_sum0),sum1(_sum1){}
data operator +(con(data)b)const
data operator -(con(data)b)const
data operator *(con(int)d)const
friend data operator *(con(int)b,con(data)a)
void operator +=(con(data)b)
void operator -=(con(data)b)
void operator *=(con(int)b)
int value(con(int)c0,con(int)c1)
// void debug()const
};int n,tot_win,tot_los;
llong m;
data g[n][2],f[n][2];
int h[n],zerotyp[n];
// int wtfdebug[n];
// h[i]=0 loser ; h[i]=1 winner
void dpdfs(con(int)u,con(int)fa)
h[u]=cnt_los>0;
for(int it=gr[u];it;it=gr.nxt[it])
} if(cnt_los) g[u][1]+=data(1,1);
else g[u][0]+=data(0,1),g[u][1]+=data(1,0);
}void rootdfs(con(int)u,con(int)fa,con(int)ph,data *pg)
tot_win+=cnt_los>0;
tot_los+=cnt_los==0;
// wtfdebug[u]=cnt_los;
if(!cnt_los)
gwin+=data(1,0),glos+=data(0,1);
f[u][0]=glos,f[u][1]=gwin;
for(int it=gr[u];it;it=gr.nxt[it]);
rootdfs(v,u,0,nowg);
} }else if(cnt_los==1)
for(int it=gr[u];it;it=gr.nxt[it])
} gwinsp+=data(1,0),glossp+=data(0,1);
gwin+=data(1,1);
f[u][0]=glos,f[u][1]=gwin;
for(int it=gr[u];it;it=gr.nxt[it])
else
} }else if(cnt_los==2)
gwin+=data(1,1);
gwinsp+=data(1,1);
f[u][0]=glos,f[u][1]=gwin;
for(int it=gr[u];it;it=gr.nxt[it])
else
} }else
gwin+=data(1,1);
f[u][0]=glos,f[u][1]=gwin;
for(int it=gr[u];it;it=gr.nxt[it]) }}
void multi(int a[2][2],int b[2][2]);
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
for(int k=0;k<2;k++)
c[i][j]=add(c[i][j],mul(a[i][k],b[k][j]));
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
a[i][j]=c[i][j];
}int main()
int res_win=add(mul(res[1][0],tot_los),mul(res[1][1],tot_win)),
res_los=add(mul(res[0][0],tot_los),mul(res[0][1],tot_win));
printf("%d\n",f[1][1].value(res_los,res_win));
return 0;
}
thanks for reading!
琴弦上羽徵角商角 羽徵角商角
不知何時才能到下一闋
琴聲下你是月上月 你是月上月
比長夜中月色更皎潔
琴瑟間曲辭疊上疊 曲辭疊上疊
遊走過的繞梁聲不停歇
讓我的心
似浮萍隨 漣漪搖曳
——《琴弦上(vocaloid)》by 樂正綾/赤羽/星葵
> link 琴弦上-bilibili
演算法之星際迷航
最近看了乙個星際迷航的題目,突然發現自己的數學水平都沒有初中水準了 說是乙個衛星發射損耗x,損耗x 2,那麼問一艘耐久度為 h 的飛行器,假設在飛行過程中不產生損耗,那麼為了保證其可以安全的到達目的地,只考慮整數解,至多發射過程中可以承受多少程度的損耗?這個題目乍一看根本不能算是演算法題啊,只能算小...
星際迷航3 父親的紀念
星際迷航3 未來之城以奇妙的引力系統,將湖水固定在天上,使人們能夠抬頭看到另乙個地面。未來高科技將引力的應用展現在我們面前的同時,這部電影還為我們展現了另外一種引力,它來至於三位父親。這三位父親並沒有出現在電影裡,但正如引力一樣,沒有出現並不等於不存在。三意味著許多,其中也應該包括我們的父親。我們,...
運輸計畫sol
運輸計畫 最小化最大值問題,考慮用二分答案 check中一般用貪心策略 將每條路徑的長度預處理,對二分的ans,將長度比ans大的取出來 並找出這些路徑是否有一條重邊使得最長的路徑減了這條邊後小於ans 注意dfs中引數少一點會更快,將dfs中訪問順序存到陣列中,在每次check時不要再次dfs 陣...