Try   HackMD

第一屆Chi怪壓常比賽 題解

首先,先感謝大家參加這次的比賽,有意見也可以私訊我! 以下是最後的記分板:

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

接著下面是題解 :

pA - 區間最小值總和問題

題意

給你一個長度為

N 的正整數數列,定義
MIN(S)
代表一個集合
S
裡面最小的那個值,想請你求
l=1Nr=lNMIN(Al,Al+1,...,Ar)

如果直接照題目所講的做,會是

O(N3)
O(N2)
,但這題
N106
,可以說是幾乎不可能通過。

O(N)
的優化

如果我們窮舉

R ,有沒有辦法移動一格就
O(1)
算出區間
[1,R],[2,R],...,[R,R]
的答案呢? 其實是可以的,我們發現從右到左,
MIN
的值其實是單調的,所以可以使用單調堆疊 (monotone stack),紀錄兩個元素
(x,y)
,代表大小和區間長度,如果現在插入的元素
棧頂的大小,那就
push
一個新的進去,否則就
pop
出來 (代表答案變小),計算「被變小」多少,之後把這些區間合併成一個新的,放一個新的進去,時間複雜度為
O(N)

另外這題似乎也有很多

O(NlogN) 的作法,如果常數不大應該也會通過。

pB - 尼姆樹

題意

給你

N 個點、帶邊權的樹
T
,有兩個人要在
T
上玩遊戲,一開始
1
上面放了一個棋子,兩個人輪流進行操作,每一個操作是選擇任何一個在棋子目前位置周遭邊權
>0
的邊,把棋子移到邊上另一頭的點,並選擇任何小於等於該邊邊權的正整數
x
,把剛剛經過的邊權減少
x
,不停輪流操作直到某一方無法進行任何操作結束,我們定義進行最後一個操作的人獲勝。請問,如果兩個人使用最佳策略,那最終是誰會獲勝?

我們可以先想想看如果邊權都是

1 會如何。

Wi=1

先觀察到一個性質,就是其實因為樹是一種二分圖,所以其實兩個人能做決定的點不會相干,如下圖 :

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

如果邊權都是

1,我們可以把他想像成一個有方向的邊 (因為一定只能從起點那邊走過來,然後不能走回去) ,而最下面的葉節點,踩到那點的人就輸了,例如上圖的點
3,5
,我們可以定義
dpv
代表踩到
v
的人最後會贏/輸,接著可以透過他的子節點的
dp
做計算,轉移式是 : 因為下面的是對手的,如果至少有一個
dp
是輸的,那
dpv
就會是贏,否則
dpv
會輸。

我們定義把全部邊權改成

1 的樹叫做
T

Wi1

接著我們回來討論我們想要的,

T 的答案,我們一樣定義
dp
,對一個決策點
v
,假設我們知道
v
以下的子樹的結果,如果
dpv
是贏的,那他明顯會走向會讓他贏的點,也就是
dp
是輸的點,並且直接把邊走完。

如果

dpv 是輸的,因為隨便選一個點下走,不論有沒有把邊權用光都沒差,在子節點上,另一個人(會贏的)肯定會繼續往下走並且走完,所以其實
T
的答案和
T
一樣。

我們可以透過

dfs
O(N)
計算出答案。

pC - 很多區間最小值總和問題

題意

給予兩個正整數

N,M,代表所有長度為
N
的正整數數列
(A1,A2,A3,...,AN)
符合
1AiM(1iN)
,總共有
MN
個滿足此條件且相異的數列,請你求這
MN
個數列對於 區間最小值總和問題(也就是pA) 的答案總和,因為答案可能很大,請模
998244353

暴力

如果照題目直接的做,枚舉所有的

A ,根據
pA
O(N)
的方法,可以做到
O(MNN)
的複雜度,雖然這東西顯然沒辦法通過,但可以利用小的
(N,M)
拿來觀察規律。

另一種思路

如果我們不計算

MN 個序列,而是計算答案是
i
的數列有幾個,我們以
cnti,j
代表答案是
i
,區間長度
j
的數列有幾個,那我們可以推得以下關係 :
cnti,j=(nj+1)×m(nj+1)×((mi+1)j(mi)j)

前面的

nj+1 是因為如果整個序列長度是
N
,那長度是
j
的部分會被算
nj+1
次,因為有區間
[1,j],[2,j+1],...,[nj+1,n]
,總共是
nj+1
個。而
m(nj+1)
是剩下不在範圍內可以隨便填的地方,因為剩下
nj+1
格,每格可以填
1M
,所以有
m(nj+1)
填法。

最後的

(mi+1)j(mi)j 是討論區間內可以填甚麼數字,如果答案是
i
的話,可以填的數字一定要是
i
(含)以上,也就是
i,i+1,i+2,...,M
這些,所以有
(mi+1)j
種選擇,然而不能全部數字都是
i+1
(含)以上,所以要扣除
(mi)j

分析

答案的話其實就是

i=1Mj=1Ni×cnti,j,這裡可以做到
O((NM)w)
,其中
O(w)
根據實作方法而改變,有可能是
O(logN)
,但其實可以做到
O(1)

進一步優化

O((NM)w) 雖然比起之前的
O(MNN)
好很多,但他當然還是不夠快,所以我們要繼續優化他

我們固定一個

j 值(下圖令
j=1
),然後看他所有的
i
,會長成這樣 :

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

答案就是表格裡面的數乘上左邊及上面的數,先把上面的數提出來,下面變成 :

i=1mi×(mi+1)x(mi)x

然後我們發現一項的

(mi+1) 的部分跟下一項
i
(mi)x
的部分是同個東西,然後前面
i
多了
1
,所以其實
i=1mi×(mi+1)x(mi)x=i=1mix

那我們怎麼快速的求

x=1ni=1mix×(nx+1)×m(nx+1) 呢? 其實我目前沒有想法,但是我們可以往另一個維度的方向看,變成求
x=1mi=1nxi×(ni+1)×m(ni+1)
,可以把
xi×m(ni+1)
看成一個部分,先無視
(ni+1)
,那他其實是一個公比
r=xm
的等比數列,可以用等比級數求和,
(ni+1)
的部分可以看成有
N
個這樣的等比數列,第
L
個的長度為
L
,把他們全部加起來,就會變成我們要的樣子,而這要怎麼加起來呢 ? 我們發現等比級數和的公式中的
rn1
這個部分的
rn
,因為
L=1,2,3,..,N
,所以其實這又是一個等比級數,所以又可以用等比級數求和 !

最終此問題可以以

O(M×(logN+logmod)) 求出答案,其中
mod=998244353

另外 oier_without_op 提到的,pC 能不能做到

O(N) 之類的複雜度,就是上面提的快速計算
x=1,2,...,N
i=1mix
的值,這目前不知道有沒有解。