SOL 星際迷航 LOJ

2022-07-05 20:06:14 字數 4892 閱讀 6064

分 類 大 討 論

給定一棵 \(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 陣...