這篇還是先紀錄下 CF #280, 雖然都是Div 2, 由於盡量會做 D & E, 基本也是D1 的A-C了..
Codeforces Round #280 (Div 2)
有點記憶不清楚, 應該都是一題一題在公司偷偷做的吧...
發現準確度的確下降了, 基本都不是一棍AC =.=
A: (頹題)
基本數學頹題吧...就不詳說了
B: (Binary Search)
bsearch的應用題, 題意大約是:
Given 一條長度為L的路, 然後一個數字d 為路燈的照明半徑, 問最少安多少台路燈
就直接Search答案 試試放下路燈能否Cover整條路就好
C: (Greedy, Sorting)
開始有吃屎感覺的一題...
題意: 有一個人要考 n 個科目, 每個科目他得到一個分數 a_i, 他可以寫b_i 份論文來把第 i 個科目的分數+1, 所有科目的分數都有一樣的上限 r , 每一科可以重覆以寫論文方式加分, 目標是把平均分大於等於 avg 分, 問他最少要寫多少論文
其實算法很直接的, 就是以 論文數先排序, 以最少論文可以加一分為先.
然後就盡量加分吧...直到那個科目已經到r 分了, 就開始下一個科目...
不知怎的實作時錯很多白痴位...
不知怎的實作時錯很多白痴位...
D: (Binary Search, Math)
這場的作者很喜歡bsearch啊...
啊咦不對..官方答案不是用bsearch的說...好像是linear time的算法
看了一下comment 還是有人提出這題可以用bsearch 解的...不算很奇特吧...
題目也很有趣, 是以電子射擊遊戲作背景。
題意: 有2個玩家要打 n 隻怪物, 第 i 隻怪物要射擊 a_i 下才會死. 玩家A跟玩家B 各自有不同的射擊速度, 一個是1秒射x發, 一個是1秒射y發, 求給予 n 隻怪物最後一擊的玩家 (可以是兩個一起)
我的想法是這樣: for 每一隻怪, 直接bsearch時間(秒數), 看看該秒兩個玩家共射了多少發, 直到找到答案(最小射得死怪物的秒數), 再來看看該秒數是否能整除 x 跟 y, 就知道玩家A跟B在該秒數有否射出子彈 (導至最後一擊)
E: (Math)
最難也是最有成功感的一題 (廢話)
題意出奇意料地簡單:
有一個 n x n 的 matrix, 有一些格子有蘋果樹 (同一格可以有數棵), 然後有一個人, 每次他移動時會以當時他的位置(x,y) 移向 ((x + dx)%n, (y + dy)%n)的格子, 他會一直走, 直到走到一個他曾經到妨的格子就完結。求他開始的格子位置, 使他整個旅程能看到最多的蘋果樹, 若有多個答案, 隨便輸出一個即可
題目確保 n 與 dx 互質, n與 dy 互質
哇...最後那句簡直是...很難不知道它就是重點...
因為這一句, 起碼有數個有用的結論可以導出:
- 不論選擇那一個格子開始 (sx, sy), 走了 k 步之後, sx 變成 sx % n + k*dx %n
k*dx %n, for 1<=k<=n, 肯定是[0,n-1]的permutation, sy同理一樣 (由於gcd(n,dx) = 1, 不記得從那學到這些number theory了...) - 由 1 可以推出: 不論從那一個格子開始, 走 n 步就會成為cycle了 (所以題目才用n x n 的matrix啊...)
- 由 2 可以推出: 一個cycle中的 n 個格子, 那一個作為開始點都沒所謂; 而不是該cycle的格子則會與另外一格子組成cycle, 總共有n 條cycle, 互相不交集
- 由 3 可以推出: 每一 row 的 n 個格子, 簡化地說, 第一row 的 n 個格子正是屬於 n 條互不交集的cycle, 而且都可以作為開始點
思路自然就變為: 比較 (0,i) 0<=i <= n-1 作為起點的cycle 的蘋果樹數目
當然直接做還是 O(n^2) 是不行的
把思路逆轉一下...選一個格子, 逆推出該格子所屬的cycle 於 第一行的格子的column數
i.e. Given (x,y), 找 (x+k*dx)%n = 0 中的k, 然後算出 (y+k*dy)%n
i.e. Given (x,y), 找 (x+k*dx)%n = 0 中的k, 然後算出 (y+k*dy)%n
由於 k 可以以O(n) precompute, 逆推這一步實施只是O(1)
以O(m) 把在(x,y) 蘋果樹數目project (歸入) (0, (y+k*dy)%n) 中
最後O(n) 找出總數為最小的格子, 該格子就是答案了...
LL n,m,dx,dy; int cx[100010], cy[100010], k[1000010]; int ans[1000010] = {0}, t = 0; int main(){ scanf("%I64d%I64d%I64d%I64d", &n,&m, &dx, &dy); for(int i=0; i<m;i++) scanf("%d%d", &cx[i], &cy[i]); for(int i=0; i<n;i++){ LL tmp = i*dx % n; k[tmp] = i; } for(int i=0; i<m;i++){ LL ny = (cy[i] - k[cx[i]]*dy + n*n)%n; ans[ny]++; } for(int i=0; i<n;i++) if(ans[i] > ans[t]) t = i; printf("%d %d\n", 0, t); return 0; }