早晨7:40的鬧鈴。到36樓下面見到了我的兩個隊友後,隨便吃了點東西就出發了。
計算中心門前特別熱鬧,n多人圍在一張大桌子前,好像是在簽到。我擠進去找了半天發現沒我的名字,名單上全是信科的人。我抬頭問,中文的在哪兒呢。乙個美女姐姐用手指了遠處的乙個幾乎沒人的地方說「中文的在那邊」,並說了一句「哇,中文的呀,太牛b了」。我順著她手指的方向望過去,另一張小桌子前面貼了「中文」二字,桌子後面沒有人,估計是交給了旁邊負責數院和元培的人,讓他們順便管一下。從我目前所了解的情況來看,那張桌子應該是特別為我準備的,它在歷史上很可能是第一次出現。
第四題是做得最順利的一道題。我把所有題粗略看了一遍後,首先決定就想這道題。題目描述巨簡單,就是問你沿對角線把乙個正n邊形剖分成三角形和四邊形有多少種方法。上圖顯示了n=5時所有的10種方法。熟悉組合數學的人都知道,三角形剖分方案對應的是catalan數列,其遞推公式的推導相當經典。設c(n)表示凸n+2邊形的剖分方案數,列舉底邊和哪乙個點相連(下圖左),容易看出c(n) = c(0)*c(n-1) + c(1)*c(n-2) + ... + c(n-1)*c(0)。
現在,如果剖分中允許有四邊形的出現,又該怎麼辦呢?看看資料規模n≤5000,估計應該是叫我們尋找類似的遞推公式。容易想到,我們可以列舉底邊與哪乙個點相連構成三角形,統計出底邊屬於某個三角形的剖分方案t(n)=σc(i)c(j), i+j=n-1;再列舉底邊和哪兩個點相連構成四邊形,統計底邊在乙個四邊形上的剖分數q(n)=σc(i)c(j)c(k), i+j+k=n-2。但是,列舉四邊形需要o(n^2)的時間,這樣的話整個程式就是o(n^3)的了,n=5000絕對超時。那怎麼辦呢?兩分鐘後,我想到了乙個具有決定意義的點子:計算q(n)可以直接利用以前算過的t(i)。列舉四邊形的兩個頂點時,固定四邊形的左邊那個頂點,你會驚奇地發現右半部分的所有情況加起來正好就是乙個t(i) (上圖右)。因此,σc(i)t(n-i-1)就是我們所需要的q(n)。
乙個有趣的細節是,這道題要求選手輸出結果除以2^64的餘數,不知道會不會有人想不到這個該怎麼處理;事實上只需要直接用64位無符號型別來運算就可以了,超界了後計算機儲存的本來就已經是2^64的餘數了。
hanoi塔那道題也是乙個有趣的數學問題。題目大意是說,如果允許hanoi塔上有相同大小的盤子,最優解又是多少。輸入資料給出盤子大小的種數和每種盤子的個數,叫你輸出最優解的步數。我的第一想法就是,大小相同的盤子始終要在一起,移動時就排著隊啪啪啪地挨個移動,總是保證大家一起行動。其實說穿了就相當於把大小相同的盤子當成乙個整體,只是移動的時候有乙個權值。這樣,只需要考慮經典hanoi塔中每個盤子需要移動幾次就行了。但很快我們發現,這連樣例都過不了。為什麼就只有兩個一樣大的盤子時,輸出會是3呢?再仔細看了一遍題目,發現麻煩了:一樣大的盤子也是可以區別的,目標狀態的盤子順序必須與初始時一模一樣。但我們很快發現,加上這個條件後對我們的原始想法影響並不大。在經典hanoi塔中,第i大的盤子需要移動2^(i-1)次,除了最大的盤子只需要移動一次以外,其它盤子都要移動偶數次。而對大小相同的幾個盤子整體轉移一次後,盤子的次序正好完全顛倒,因此移動偶數次後次序不變。於是,我們只需要集中考慮最大的那種盤子該怎麼處理。隊友leimiaos做出了乙個大膽的猜想,事實證明他是對的:把最底下那個盤子加大一號(最大的那種盤子就變成第二大的了,並且少了乙個),這樣就巧妙避開了多個最大號盤子的問題;這樣做的結果顯然是合法解,並且應該是最優的。
第一題是所有題目中最科學的一道。給你乙個有向圖,給定它的起點和終點。每一條邊都有且只有一段開放時間,其它時間裡這條邊是不允許通過的。給出每條邊的開放起始時間、關閉時間和通過這條邊所需要耗費的時間,問你從起點到終點最少需要多少時間。我和leimiaos同時想到,在這道題目中我們要盡可能早地到每乙個點,可以用直接套用dijkstra演算法更新到每個點的最早時間。反正你早到了也不虧,如果接下來要走的邊還沒開放的話我等一下就是了。leimiaos很快寫完了這道題,但連樣例都過不了。仔細研究了一下樣例,我們發現問題嚴重了:我們要求的不是到終點的最早時間,而是從起點到終點全程所需的最少時間。換句話說,我可以先在起點處等著不走,看著時機成熟後再出發,雖然到終點時間更晚,但路上花的時間更少。怎麼辦呢?列舉出發時間是乙個好辦法,但時間的範圍很大,肯定會超時;二分出發時間?顯然不行,這個問題不具有單調性(考慮從起點直接連到終點的多重邊,且所有邊的開放時間都不相交)。十分鐘後,我一拍大腿說,至少存在乙個最優解,使得整個路程在某條邊上正好卡著時間進去或者卡著時間出來。如果整個路程中所有邊上的實際通過時間都是「松」的,就把整個行程時間安排挪動一下,直到某條邊上的通行時間正好碰到開放時段的端點。這樣的話,我們只需要列舉整個行程時間卡在哪條邊上,然後用剛才的演算法順著推出從這兒走完剩下的路到終點的最早時間,並且反著推出從這兒往回走能夠得到的最晚出發時間。這道題太精彩了!!可惜後來時間不夠,演算法的**沒有完成,演算法的正確性和效率也不得而知了。
第二題是一道很難的數學題,很少有人做出來。因此我非常得意:) 說乙個n階的滿steiner樹是指乙個有2n-2個節點的無根樹,其中n個葉子節點從1到n標號,另外n-2個節點(叫做steiner頂點)連通了那n個點,並且每個steiner節點的度都為3。你可以在這裡看到n=3時的惟一乙個滿steiner樹,以及n=4時的所有三個滿steiner樹。輸入乙個n(3≤n≤10^7),輸出n階的滿steiner樹有多少個。要求用8.687e36這樣的格式輸出。
隨便把乙個葉子節點砍掉,剩下的就是一棵正宗的二叉樹,我們的問題實際上就變成了「有n-1個葉子節點的二叉樹有多少個」,其中葉子節點帶標號,並且二叉樹不分左右。依據這個思路得到的遞推公式就是( σc(n,i)f(i)f(n-i) )/2,那個c是組合數的意思,f(n)表示n階滿steiner樹的個數。但是n可能達到10^7,絕對不可能直接用我這個遞推公式。我開始計算n=3, 4, 5, 6的情況,想看看有什麼數學規律沒。算出來的數是1, 3, 15, 105。然後牛b的事情就發生了,我眼睛突然一亮,發現它們間的比正好是3, 5, 7,也就是說f(n)=(2n-5)!!!(前兩個嘆號是雙階乘的意思,末乙個感嘆號是感嘆號)。我立即寫下乙個程式,按這個公式計算f(30),發現它果然得出8.687e36,和樣例一模一樣!
真正戲劇性的事情發生了:暴力計算雙階乘超時了。怎麼辦?注意到,(2n-1)!!=(2n)!/(2^n*n!)。leimiaos突然想到,在這個精度要求下完全可以用stirling近似公式。我們可以讓n到了一定大時利用stirling近似公式直接輸出結果。n的階乘約等於根號下(2πn)乘以(n/e)^n,在比賽中我們發現這個公式的精確程度令人瞠目結舌。非常神奇地,π和e居然出現在了階乘的近似公式中!
最後的結果,我們只ac了10道題中的4道。acm果然是拼時間的,好多題目我們都會,就是沒時間寫了。我n多年沒寫過**了,昨天絕大多數**都是leimiaos寫的。也好嘛,這次就是抱著玩玩的心態來的,也長了一些經驗。明年賽前我可能真的會認真準備一下。還有三年的機會呢,慢慢來吧。
整場比賽的第一名ac了8道題,其中5道都是一次通過。你們猜這個隊伍是哪三個人?告訴你,牛大b了,真的牛大b了。三個人分別是唐文斌、郭華陽、王棟。這次比賽是允許外校隊伍報名參加的。
最後,非常感謝網友dahe_1984請我吃飯喝酒!昨晚的聊天非常愉快,喝得也很盡興。
《吉林大學ACM集訓隊選拔賽》
a 數字dp。dp i 表示從小到大第i位時的貢獻。可以發現。當第i位為7時。它的貢獻即為 i 1 n 10.即70.71,72,73,74,75,76,77,78,79.對於每一位都有10個數。0 10有10個.0 100有100個.所以可以預處理出這個數。顯然可以發現,當該位沒有到達上界時,下面...
西北大學選拔賽03 A 會拐彎的眼睛
那不是咱們的酒店 風向標 麼?zjt剛出長沙車站,就指著遠處的乙個樓說。旅途疲倦的大家瞬間又打起精神,準備趕緊到酒店休息。然而從車站出來的路途卻是九曲十八彎,大家經歷了無數的十字路口,繞來繞去,反覆探索,才在乙個角落的牆壁上看到了 風向標 三個字。你眼睛會拐彎,剛一出車站就能看到?就是你觀測到了黑洞...
飽和式救援,西北大學集訓隊選拔賽(重現賽)
在全球性救援開始的0.42秒後,moss就已經推算出結果,這是一場注定徒勞的救援。在 流浪地球 電影中,雖說在引爆木星之後推動了地球離開木星,但是大 摧毀了地球上大部分的行星發動機。人類再一次展開全球性救援。此時的moss已經被燒毀,現在告訴你每只救援隊的目標發動機的編號以及這只救援隊在規定時間內成...