2015年4月28日 星期二

UVa12907-12915

緩慢更新中...感謝 morris821028 幫忙寫 code 驗證我理解是否有誤 m(_ _)m

12907 Toby the adventurer 

題意:有一塊大陸,有 $N$ 個城市,以及 $M$ 條單向道路,每條道路有對應的通行費,有一個人要在這塊大路上冒險,最初他在邊號 $R$ 的城市,他可以付一條路所對應的費用,延著該條路的方向,到一個新的城市,此外,他可以不用付任何費用就回到任何一個他已去過的城市,請問他至少要花多少錢才能逛完所有城市?並輸出旅行的方案。若無解則輸出 impossible。

數據範圍: $測資組數 \leq 100, 3 < N \leq 10000,3 < M \leq N,0 \leq R < N$。

tag:[ 圖論 ]

  乍看之下這題就只是個 DMST (Directed Minimum Spanning Tree) 問題 (一般情況可使用 Edmond's algorithm 解之),且是一個要輸出解的 DMST。但大家應該有發現他有一個超怪的條件: $M \leq N$ !事一定有蹊蹺!?

  首先有件很理所當然的事: $N$ 個點的 DMST 恰有 $N-1$ 條邊。所以我們可以藉此聯想到一個 $O(N^2)$ 的演算法:考慮 $N=M$ 的 case,我們可以枚舉要刪除哪條邊,並 $O(N)$ check 剩下的邊是否為一個合法的 DMST。若 $M<N$ ,答案應該蠻顯然的。

  接下來可以想想看,我們真的要枚舉那麼多種可能性嗎?首先注意到,合法的 DMST 中,每個點的 in degree 幾乎都是 $1$,但 $n$ 條邊 in degree 的總合只有 $n$ 的 ,實際上,除起點外,若有哪個非起點的點在原圖中的 in degree 是 $0$,就沒有解;若 in degree 是 $1$ 則非得選不可。所以可選可不選的邊至多只有兩條!找出那兩條,然後枚舉哪兩種可能看看哪個比較好,就解決這題了。

  若真的遇到 DMST 找解的問題,可是非常痛苦的 ...,我比賽中在解 DMST 問題時,總是直接從 codebook 複製貼上。但是現今大部分的人所使用的 codebook 都沒有包含構造出一組 DMST 解這件事,所以就必須好好重新想想 Edmond's algorithm。實際上,2013-2014 NEERC 就有一題要構造出解的 DMST 問題: UVa 1681 Dictionary,大家可以試著去挑戰他 XD 挑戰完把他加進 codebook XD

  若有在 UVa 找最經典的 DMST 問題:則請看 UVa 11183 - Teen Girl Squad

12908 The book thief

題意:有一個小偷把一本書的所有頁數數字加起來,但漏加了一個數字,告訴你小偷算出的總和的值,請求出該本書有幾頁以及漏加的是哪個數字。

tag:[ 數學 ]

嗯...可以 O(1) 快速得知至少需要幾頁 (1加至總頁數必須大於 input 值),再 check 是否能減掉某個數字就得到 input。實際上你總是能得到一個合法的漏掉的頁數唷!

12909 Numeric Center

題意:給定 $n$,請問 ${1}$, ${1,2}$,${1,2,3}$, ... , ${1,2, \dots , n}$ 的集合中,有多少個集合,能在集合中恰找到一個數 $x$ ,使得集合中小於 $x$ 的數的總和和大於 $x$ 的數的總和相等。例如說,集合 ${1,2,3,4,5,6,7,8}$ 可選 $6$ 為 $x$,使得 $1+2+ \dots + 5 = 7+8$。

tag:[ 數學 ]
關鍵字: Pell's Eaquation

  據說這題只要把最小的幾個數搜出來再拿去 google 就能 google 到數學公式了。

  若要自己解,可以先列出關係式,據說化簡後會得到 $8*x^2 + 1$ 必須是完全平方數,也就是說 $x$ 式所有 $y^2-8*x^2 = 1$的整數解。這東西叫做 佩爾方程,可以 google 到很多關於這東西的資訊,他可以使你用手算一算後很快的得到所有 $x$ 的解的遞推公式。

12910 Snakes and Ladders

題意:蛇梯棋遊戲,使用公平的六面骰,問結束遊戲時的步數期望值。
tag:[ 數學 ]
關鍵字:高斯消去

  就...一臉高斯消去樣,把期望值的關係式列出來後解聯立方程式。

12911 Subset sum

題意:給 $N$ 個數的集合,請問有多少非空子集的集合內數字總合等於給定的值 $T$。
數據範圍:$1\leq N \leq 40$。
tag:[ 小品 ]
關鍵字:分兩半

  通常看到 $N = 40$ 附近的問題... 就會值接兩響到把數據切成兩半的做法。這題的類題不勝枚舉,把集合拆成兩半,每半部的集合都枚舉所有 $2^{N/2}$ 種subset,枚舉其中一半部時 hash 每個總合的值出現多少次,而枚舉另外一半部時,就可以根據hash值得知他有多少種和前一半部的組合加總可以湊成 $T$。

12912 Josephus lottery

題意:有 $N$ 個人圍一圈,由順時針分別從 $1$ 號編號到 $N$ 號,由 $1$ 號開始數,第一輪順時針數 $K$ 個人,並把被數到 $K$ 的人移除,下一輪從被移除的下一個人開始數,但這次是逆時針數 $K$ 個人,一樣把第 $K$ 個人移除,如此反覆順時針逆時針交互的數,直到只剩下一個人,請問剩下的人編號是多少?
數據範圍:$1 \leq \leq K \leq N \leq 10^6$。

  就約瑟夫問題變形。雖然 $N$ 很大,但 $O(N log N)$ 做法就可以 AC 了。與一般的約瑟夫問題一樣,可以倒著用 $O(n)$的時間複雜度 dp 回來。

12913 Grounded

題意:給定 $N$、$K$,$S$ 為包含 $0 \sim 2^N - 1$ 間所有整數的集合,請問 $S$ 有多少子集合滿足集合內所有數的 xor 結果,轉乘二進位後恰有 $K$ 個 bit 是 1。

數據範圍:$1 \leq K \leq N \leq 10^6$
tag:[ 數學 ]
關鍵字:集合

和 Hackerrank 上的 Ad Infinitum 10 - Math Programming Contest Number of zero-xor subsets 概念一模一樣,差別只在於 Hackerrank 那題只問 $K = 0$ 的 case,所以去參考Hackerrank 上的 Editorial 理解後應該也能做出這題。

我來用我自己的方法解釋 $K = 0$ 的 case。 $K = 0$ 意即該集合所有數的 xor 結果為 $0$。先隨便亂抓一個集合,例如說 $N = 3$ 時,我們任取一個集合:{2,3,5,6},這四個數 xor 結果為 $2$,並不是 $0$,現在我們想要把這個集合稍做修改,讓他變成 $0$,要怎麼做呢?應該會很直覺的把集合內的 $2$ 去掉吧?那若現在取的集合是 {4,6} 呢? 此集合 xor 後的結果也是 $2$,那我們就可以把 $2$ 加進這個集合裡,能使集合的 xor 值也變成 $0$。

於是我們可以發現,任取一個 $S$ 的子集,我們都有辦法恰對集合新增或移除一個數,讓集合內所有數 xor 結果為 $0$ (注意我們新增或移除的數可能是 $0$),且方法恰只有一種。所以說,總共有 $2^{2^N}$ 種子集合,我們就能變出 $2^{2^N}$ 個 xor 值為 0 的集合嗎!?當然不可能啦 XD 實際上,會有好多個集合改變後會對應到同一個集合,那麼一個 xor 值為 $0$ 的集合,會被幾個集合對應到呢?例如 $N = 2$ 時,{1,2,3} 集合內所有數 xor 值為 $0$,而會對應到他的集合有 {0,1,2,3}、{2,3}、{1,3}、{1,2} 共四種。到這裡應該能看出點頭緒了吧?對於每一種集合內所有數 xor 值為 $0$ 的集合,都恰有 $2^N$ 個集合能經過加減一個元素的操作對應到它。所以全部 $S$ 的子集合,每 $2^N$ 個集合會對應到一個 xor 值為 $0$ 的集合,故全部共有 $(2^{2^N})/(2^N)$ 個 xor 值為 $0$ 的集合!這也就是 hackerrank 那提的答案。

至於 $K$ 不為 $0$ 要怎麼辦呢?剛才我們解的是 xor 值為 $0$ 的集合數,那 xor 值為 $1$ 呢? xor 值為 $2$ 呢?能如法炮製嗎?

12914 Sum of all permutation


12915 TripleCorn


正常的 dp 優化題?

2015年4月27日 星期一

Codeforces Round #300 參賽記錄

比賽連結
Editorial 連結

  這場比賽我除了解題順序不認真以外,其他部分我可是非常認真的!在賽中完全沒有想過要去 challenge 別人!有人在賽中敲我 g+ 我也沒回應!但是名次好慘呵,我花了一個小時左右寫完了 C、D、F 後,直接打開 G,剩下的一個半小時都栽在上面了,賽中剩下 20 分鐘才想到解法,賽後一個小時左右才 AC。最後 rank 371,連抽 T-shirt 的機會都沒有。還有人問我是否想要再一次變成藍色,聽到別人這樣問我我好傷心喔 XDDD,我這幾場都有好好的比耶 XDDD 只是最近的比賽不小心把我的實力揭露出來讓我連掉五場 rating XDDD 最近的幾場比賽大都是比較大型的比賽諸如 VK cup、ZeptoLab Code Rush 之類的,每次遇到大型比賽我的名次就會變糟糕 ... 這是心理壓力的關係嗎?

  最近總是直接寫題目的解答,這篇來回覆一下我以前在 BBS 使用的方式紀錄比賽,把比賽過程中我在思考什麼,在哪些地方卡住等資訊近可能的保留下來。

  這場比賽,我想要犧牲一些解簡單題的時間,來換取更高的賽中 AC 難題的可能性,所以開場就直接從 pC 看起,看完後我就立刻連想到了 CF534 B - Covered Path,都是類似的概念,相鄰兩個時間點直不能超過給定值的題目。可是我的思緒很混亂,寫出了比較複雜的做法,明明就寫一個 for 迴圈就能解決,我卻寫了兩個,順的跑一次逆的也跑一次,還出了點 bug,結果13分鐘才 AC,這時候已經有不少人前三題都寫完了 =口= 結果我先寫 C也沒省到多少時間嘛 = =

  接著我直接看 pD 也是個還算直覺但要把他寫成 code 無法立刻想到好寫的做法,但我還是憑直覺寫下去了。總之就是先簡查哪些向量若可以選就一定要選他,在檢查看看使用這些所有選的向量是否能攻擊到所有得被攻擊到的位置。是說這題 Sample Output很心機,硬是要和大家直覺寫出來的 Output長的不一樣...。我原本漏考慮了有可能會攻擊到盤面外部的 case,使得 Output 總是輸出 NO,我大概花了兩三分鐘才 de 出這個問題,後來修正後 output 還是和 Sample Output不一樣 = =,check 了一下才確定我的 output 確實也是正確的。

  我寫完兩題後已經有人寫了五題了!挫敗感很高耶,我決定跳過 pE,直接看也有人在短時間 AC 的 pF。pF看完我立刻往複雜度 $O(n \sqrt{n})$ 的方向去想,因為讀完題目後立刻從我腦海裡浮現的知識是:每個 node 當 $k$ 的值從 $1 \sim n-1$,在改變時,他的父節點可能只會改變 $O(\sqrt{n})$ 次,這就和 $n$ 固定,$k$ 會改變時 $\lfloor n/k \rfloor$ 的可能值至多只有 $O(\sqrt{n})$ 很像,因為父節點的編號實際上就是 $\lfloor (x-2)/k \rfloor + 1$,所以要解這題,我們只需要把每個節點的的可能的父節點都各別求出來,以及會對應到該父節點的 $k$ 值個數也求出來就行了。於是讀完題想不到一分鐘我就立刻開始寫 code,但是寫到剩最後一部分 --- 記算父節點的編號以及有多少 $k$ 值會對應到該編號,我卻卡住了,我腦袋轉不過來 ... 每次我在認真比賽的時候,都不太能進行這類比較複雜的計算 ... 團體賽的時候我還可以秤隊友還在 coding 時,在旁邊深呼吸,想辦法靜下心然後在開始動筆計算,可是在個人賽的時候我幾乎無法靜下心做這件事,啊啊啊該怎麼辦 >_<

  這時我想法亂成一團,在思考要不要靜下心好好動筆算的時候,有想到了令一種思考此題的方式 --- 上段所述的方法是固定子節點,思考父節點的變化。但我們可以從另外一個角度:考慮每個父節點,看看他有哪些子節點,我們可以發現,當 $k$ 愈大的時候擁有子節點的節點數量為 $O(n/k)$ ,所以若先把所有父節點所擁有的子節點區間都離線存下來,就可以 $O(n \log^2{n})$  (因為總共有 $O(n \log{n})$ 個區間) 配合 BIT 掃過求出每個父節點有多少子節點的值比自己大。原本我有點擔心這樣會不會花太多記憶體儲存,但你若有仔細看這題的記憶體限制,會發現這題的限制是 $512$ MB,比預設的 $256$ MB 還大,就會發現 author 預設的解法大概就是這個做法吧?要不然上一段的做法根本不需要什麼記憶體 XD 這個做法想清楚後,我就把原本寫的 code 果斷砍掉了 ... 重寫新的做法,寫完 Sample 對了之後我還自己生了最大的測資測了我的 code 的速度,看來是沒什麼問題後才 submit。我寫完三題時,已經有不少人把前六題都寫完啦!!!

  隨便點了幾份 pF 的 code,兩種做法都有了寫,第一種做法的程式碼可以參考 rng_58 的 code,寫的非常精簡,而賽中14分鐘就 AC 的人則是使用第二種方法,他沒有離線預處理,而是使有了比較複雜的資料結構 (WaveletTree?這什麼東西@@) 使得可以 online 快速知道一個區間內有多少數小於給定值。

  上傳 pF 後,我鐵了心直接挑戰 pG。 pG 題目非常簡短如下:

有一個長度為 $l$ 由 ULRD 所組成的上下左右的移動指令,你並不知道指令的 pattern 長怎樣。有一個機器人起點在 (0,0),每一單位時間依序按照這串指令直性移步並移動一單位距離,若這串指令都執行過,會再從頭開始用同樣的 pattern 繼續移動。告訴你這個機起人某些時間點的位置,請找出一種可能的 pattern 或輸出無解。

   這題感覺起來有點數學,又有點差分約數的感覺?我覺得我一定能解出來!但是想了許久就是沒什麼想到什麼明確的起手步,是因為有一點點精神不濟想睡覺的關係嗎?先把題目化簡移下好了,這題是二維的,如果變成一維的話我要怎麼做?想到這裡,我就發現,若會做一維,也就是說只有LR兩種指令的版本那麼我們就可以解二維的了!因為我們可以把U, R以及 L,D 分別是為同意種指令,若是 U,R 的指令那麼機器人所在的座標 $(x,y)$ 中 $x+y$ 的值就會加 $1$,若是 L,D 則會減 $1$。固解出一維的 case,我們就能月定pattern的每個指令會是L,D兩者之一或是 U,R 兩者之一。接著我們在改成把 L,U 和 D,R 個別綁在一起,做出來後就能就能得所有指令了!

  轉換成一維(只有 L,R 兩種指令) 後我仍舊卡了很久,要按照時間序考慮問題嗎?還是按照時間 mod $l$ 的值由小到大考慮問題呢?如果有出現兩個時間 mod $l$ 的值相同又會怎樣?我們就可以得到整串指令移動完的為移會是多少,知道這件事後又怎樣?知道這件事後我們就可以按照時間 mod $l$ 的值由小到大考慮所有已知機器人的位置,做一些運算後,得知很多諸如 (前 $i$ 個指令移動完位移將是 $d_i$ ) 的資訊,如果 $d_i < 0$ 或 $d_i > i$ 或 $d_i$ 和 $i$ 的奇偶性不同就不合法,否則就可以貪心的填入 $(d_i + i)/2$ 個 R 進去之類的。所以若有兩個已知機器人位置的時間點 mod $l$ 結果相同,我們就可以得到正確的 pattern!所以我解決的其中一種 special case!但這要怎麼推廣?完全想不到啊 >_<

  這種 special case 我們能確定 pattern 的主因是我們知道了整個指令群移動完的位移的值(令其為 $ds$),所以我們若能確定該值,就解決了吧? $ds$ 的值的可能性有 $0 \sim l$ 那麼多種,有辦法縮小其範圍嗎?有沒有可能同一組測資擁有不同的 $ds$ 值的合法解呢?這麼說來剛剛我們確定了 $ds$ 就能知道每個區間內有多少個 R 指令,所以說我們若把每個區間內的 R 指令個數當成變數,稱其為 $r_i$ 之類的,那就可以把 $ds$ 和 $r_i$ 列出線性等式吧?而且我們擁有 $ds$ 和所有 $r_i$ 的上下界( $ds$ 的上下界是 $0$ 和 $l$, $r_i$的上下界是 $0$ 和 該區間大小),那是否存在某種快速枚舉這些變數的值的並判定有無合法解的演算法呢?嗯... 若枚舉了任何一個變數的值那麼就可以 $O(n)$ 判斷是否有合法解了,若枚舉 $ds$ 的 $O(l)$ 種可能值,那複雜度最高就是 $O(ln)$ 有點大耶?嗯... 某種程度上這些區間是型成環狀的... 環狀?枚舉!?這件是好像有印象!那不就是 CF526 E 的其中一種算法嗎?因為有 $n$ 個區間,所以至少有一個區間 size $\leq l/n$,所以就會至少存在有某個變數要枚舉的可能性 $\leq l/n$ 於是找出該變數並枚舉的複雜度會是 $O(l)$!於是我就解出來啦!想到這裡的時候,比賽已經剩不到 $30$ 分鐘了 0.0

  最後寫 code 時發現使用這種做法還有好多好多 special case 要處理 ...  那些 $ds$ 在等式中係數可能是 $0$ 之類的問題,或是所有時間點剛好 mod $l$ 都是 $0$ 的問題(我覺得這個 bug 思考時不會漏掉的一定都是怪人!)。

  AC 候我就在想,我使用了一個那麼奇怪的技巧來 AC 這題,想必不是 author 所用的解吧?而且這個技巧不久前才出現過耶?後來看了其他所有 AC 的 code,果然只有我使用這個方法 ...,我忽略了一件很重要的事:所有聯立等式中 $r_i$ 的細數都是 $1$ !所以對於每個 $q+i * ds + r_i = v_i$ 的等式,我們可以根據 $r_i$ 的上下界來更新 $ds$ 的上下界,若全部等式更新完後 $ds$仍有整數解,那麼代入任一個 $ds$ 的整數解給所有式子後一定能得到在合法範圍裡的 $r_i$ 的整數解。於是 $code$ 應該能變成更簡單一些,根本不必枚舉某個變數的所有可能值啊!若...我在看到這題時,碼上就把所有該列的變數該列的等式列出來在紙上,是否能快一點想到呢?但我相信拿麼做的話就不會產生我這種奇葩的解法了 0.0

  呵呵在最後一步採用了有點多餘且非常獵奇的方法,我該為此感到自豪還哀傷呢?

  賽後看了剩下的題目, pA直接暴力枚舉即可。pB 就是一個很直覺的 greedy。 pE 就普通的 tree dp,記算可能要小心一點。 pH,嗯... 感覺起來不太難,要歸類為 greedy 吧?想了一下細節,覺得應該就是那樣了。不過 pH 目前 最短的AC code 值得研究研究,他的解題步驟和我的思考順序並不一樣,我還不知道怎麼證他的做法的正確性 ... 證出來並覺得很有意思的話再分享吧?

  如果我這篇相較於過去的解題報告,寫的讓大家完全看不懂,想必是很正常的一件事...

2015年4月26日 星期日

TLX Open Contest Beta Round #1

昨天心血來潮就寫了一下這個據說是APIO熱身賽的東西 (Invitation from Codeforces)

題目感覺上都蠻普通的,APIO 應該會比這些題目難很多吧?題目品質也有點問題,pB、pC都有嚴重的 issue ,賽中才被更正。

是說 SRM656 的解題報告寫了一半覺得好難寫,先跑來寫這個簡單的東西 wwwwww

題目連結(必須登入)

Problem --- Social Inequality

題意:給 $N$ 個點,問有多少任兩個點所圍出的矩形的面積總合。

數據範圍:$1 \leq N \leq 10^5$,所有點座標介於 $0 \sim 10^4$

關鍵字:[ D&C ]

tag:分治法
= = = = = = = = = = = = = = =
這題正好可以看出我在解題時會怎樣去聯想以做過的題目。它給了平面上好多點,又問了關於所有矩形的某些資訊,於是我就聯想到了  ZeptoLab Code Rush 2015 pF,是我過去寫過題解的東西!(我每次列的關鍵字終於用到了 XD 輕鬆搜到這題 ),於是我就開始思考要怎樣用Divide and Conquer 來解這題。

使用的 D&C 來解這題的話,大制概念就是每次把點群都分兩半,把兩對角恰在兩半各一個的矩行面積總和先算出來,再遞回下去。

這題時限只有 0.3 秒,看來一定得用 $O(n log n)$ 的解法才能 AC,所以在每次解一個 subproblem 時,只能用 O(n) 去解決 (這裡的 $n$ 是該 subproblem 的點數)。

仔細描述一下我們要解的 subproblem:
  平面上有很多點,以及一條水平線,請把所有水平線上及水平線下各曲一點的所有組合,每個組合所圍成的矩行面積總合計算出來。

不防假設我們已經把所有點由左到右排序好了。接著我們由左到右一個點一個點依序加入,每加入一個點時,我們希望能以 $O(1)$ 的時間,把該點與所有在另外一半的已加入點所圍成的矩形面積總合算出來。

如下圖所示,假設現在加入的是在下半部的藍點,而在上半部已存在的點是三個紅點。要一次行算出所有的面積似乎有點困難,但我們若再把每個舉行細分為上半部和下半部,就會發現要一次把所有矩行的下半部面積總合算出來(或是上半部),都沒有很困難。

例如說我要算下半部的部分,我們可以發現所有下半部的矩形高都一樣,在新增藍點時才會決定(令其為 $h$)。所以我們若能知道所有矩行寬的總和($\sum w_i$),就可以算出所有下半部的矩形面積總合($\sum{w_i*h}$),以下圖為例,令藍點 $x$ 座標為 $x_b$,紅點座標為 $x_1, x_2, x_3$,則 $\sum{w_i} = \sum{(x_b - x_i)} = 3*x_b - \sum{x_i}$。所以實際上我們只要記錄每一半部已經加入多少點,加進去的點的 $x$ 座標和,就可以快速算出加入的點所在的那半部矩形面積總合。

而另外一半部也能使用某些累加的概念去算出面積總和,詳情請參考我所付的程式碼 >_<

若要認真考慮 Divide and Conquer 中的 Conquer 到底有沒有在這個解法起作用...其實我覺得並沒有 ... 所以還是稱它為分治法好了 Orz



我的程式碼如下:

Problem --- Jump!

題意:有無窮多的個石頭,並把它們用正整數編號。每個石頭都有個對應的值 $a_i$。有多個詢問。詢問過程中要維護一個數 $N$。第一種詢問:給定 $N$ 的新的值。第二種詢問:更新給定編號的石頭的值。第三種詢問:你可以選擇一個數 $P$ ($2 \leq P \leq N-2$ 或 $P = 0$),最初會先把石頭 $1$ 標記,接著會把石頭 $(P$ mod $N) + 1$,  $(P*2$ mod $N) + 1$, $\dots $ 也標記,直到再遇到石頭 $1$ 為止,請問選哪個 $P$ 值,能使得被標記的石頭所對應到的值總和最大($P$ 若選 $0$ 代表指標記邊號 $1$ 的石頭)?請輸出最大的總和值。

數據範圍:$1 \leq N \leq 2000$,詢問數 $\leq 50,000$。

關鍵字:[ 資料結構 ]

= = = = = = = = = = = = = = =
這題題目敘述很複雜... 而且一剛開始 $P$ 的範圍還給錯使我 WA 了好多次。

首先要注意到雖然我們選的 $P$ 值可能不同,但若 $gcd (P, N)$ 相同的話,標記到的石頭們會是同一群,也就是所有邊號為 $gcd(P, N)$ 的倍數加 $1$ 的石頭。方便起見,值接把所有石頭邊號減一會比較好寫 code。

注意到這件事後,我們就知道對於每個第二種詢問,只需要考慮是 $N$ 的因數的 $P$ 值 (當 $N \leq 6$ 時,有可能不存在合法的 $P$ 使得 $gcd(P,N) = 1$,要特別處理)。並且在枚舉這些值時,可以用一些資料結構如樹狀數組(Binary Index Tree, BIT)去算加總。

詳情參考我的程式碼:


Problem --- Fowl Scupltures

題意:平面上有好多個點,以及一條通過原點的直線,這些點是兩兩成對的,也就是說所有點對於該直線的隊稱位置也會有一個點。但現在某些點消失了,並且我們也不知道直線在哪(只知道它通過原點),問至少消失幾個點,以及直線可能的位置(若有多種可能位置請選取最離 $x$ 軸政像逆時針角度最大的位置)

數據範圍:點數 $\leq 2000$,所有座標絕對值 $\leq 10^9$。

關鍵字:[ 計算幾何 ] [ 枚舉 ]

= = = = = = = = = = = = = = =
這題其實有個很大的癥結點:題目沒說明點若恰好在那條直線上會發生什麼事,若造測資條件所述:"No two or more sculptures are located on the same coordinate." 那麼點應該不能出現在直線上,可是沒有判這件事也會 AC (判了說不定會變成 WA?),總之先無視這個問題...

要使得消失的點最少,也就是要使得配對到的點對最多。並且每個點對若能配對,也都會有個配對時會對應到的角度。於是我們枚舉任兩點能夠配對時的角度,只留下角度的資訊,可哪個角度出現最多次,那個角度就是答案了。至於對稱軸的角度,在這題裡可以使用向量取代,於是不會有浮點數誤差。細節請看程式碼註解。

我的程式碼: