ABBYY Cup 3.0 - Finals(總結)

題目鏈接

D題真的有點難寫,,,不過寫完後發現,也還行(我冒着可能萬劫不復的心態研究了下tourist的代碼),儘管如此,寫的時候還是感覺各種不順,還好1A了,不過肯定得重寫,。這種題非常鍛鍊代碼能力。

這場比賽如果參加的話能暴漲啊。虛擬比賽的時候很快就做完了A B C ,然後D題不會做,暴力懶得寫,寫了的話估計還能漲點。

A題:

題意給你一個序列,讓你挑出一個子序列,子序列的兩端必須是一樣的數字,然後要使得總和最大。

考慮到選的數肯定越多越好(就算是負的,但是可以去掉嘛),所以我們只需要記錄下所有的pair,first表示第一次出現的位置,second表示第二次出現的位置,然後就是枚舉所有的pair,去除區間內所有的負數就好了。

B題:

題意: 

給你一個排列,長度是3*10^5 , 有兩種操作

1:將兩個位置的數互換

2:詢問從x到y的連續的數在現在的序列中需要取幾次,注意:每次可以取出一個子序列,但是隻能是遞增的。

想了一會就想出來了,要判斷取幾段其實可以用線段樹區間合併,sum[rt] = sum[rt<<1] + sum[rt<<1|1],如果說中間的m 和m+1位置能接上去,那就sum[rt]--,

C題:

題意:給你一個數,最大有10^18,現在每次要將這個數減去數位上的某個數,然後一直減,問你最少需要幾次操作能將這個數減成0

首先是小數據,10^6,看到樣例我們或許就能發現什麼了,每次減去數位中最大的一個數就能最快的到達0,。爲什麼呢?這個可以用數學歸納法證明。



現在我們有了這樣一個結論,假設f[i]表示將i變成非正數的最小代價,那麼如果dp[i]是非遞減的,我們是不是每次只要儘可能的減小當前的數就好了呢?顯然使得。

所以我們現在就是要證明f[i]是非遞減的,即單調的。

貼一段CF上的評論:來自niklasb

Let f(n) be the minimum number of moves needed to reduce the number n to zero by repeated subtraction of one of its digits.

Let D(n) be the set of digits of a number n. We have the recurrence f(0) = 0.

I will prove to you by induction that f(n) is monotonically increasing, which means that subtracting more is always better, which implies that the greedy approach is correct.

Claim: 

Base case: Obviously f(1) = 1 ≥ 0 = f(0), so the claim holds for n = 1

Inductive step: Let  and  (so f is monotone on the set{0, ..., n - 1}). Let k be the largest digit of n. By a simple case analysis, we can see that n - 1 has a digit l ≥ k - 1. Using the monotonicity of f, we conclude

In addition, we know that . Since k = max D(n) and because we assumed the monotonicity of f on the set {0, ..., n - 1}, we know that f(n) = 1 + f(n - k). Combined with the above inequality, this gives us f(n) ≥ f(n - 1).

本來想自己寫一下,無奈數學工具啥的不會用啊。。

好了,既然我們已經有了上述結論,那麼對於一個數

10^6顯然可以暴力,不解釋。。

10^12呢,也是可以暴力的

我們將10^12分成兩段10^6的數,左邊是n/10^6,右邊是n%10^6,所以這樣子的話每次只要將右邊那個10^6級別的數用O(1)時間計算出他的最小次數以及他將變成什麼數(一個非正的個位數),這個時候左邊的數再借位過去,只需要暴力10^6就可以了,每次都減少了10^6嘛。注意到我們在減去右邊的那部分數的時候左邊的數的最大值也要考慮進去,所以加個狀態就ok了

cnt[i][j]表示左邊的最大值爲i,右邊的數爲j時將j變成非正數的最小次數

derc[i][j]表示同上的狀態下這個數變成了什麼

具體代碼可以參考最下方的鏈接。

接下來我們來搞定10^18吧,我感覺10^18需要對狀態的分析與總狀態數的計算有一個清晰的邏輯,不然絕對是不會做這個題的。

10^12的那種暴力的方法其實還是沒有利用到一個非常特殊的性質。每一次將後面的數變成非正數之後,借位後新的數的形式其實是a*10^p-b,a是前面數位的最後一位,所以顯然這樣的總狀態數是及其有限的,但是數組是沒法想c2那樣開了,但是我們還是想知道同樣的信息,比如2856987,將856987變成非正 的最小次數與變成了什麼,這兩個信息,然後再一步步將當前的2856987變成非正的,再返回上一層去。其實開了map映射下就好了。

D題:

題意:有一個b*b的網格,網格中有n個箭頭,都是和座標軸平行的,現在有一些詢問,類似於告訴你起始點,起始方向和進行的時間,求出最終位置。

範圍的話都是10W級別的,時間t是10^15級別的。

起始對於某個位置往某個方向,我們是可以知道最近的箭頭是哪個箭頭的,,那麼我們將每個箭頭都與該方向最近的箭頭串聯起來,是不是會形成一條條的鏈或者環,關鍵點是每一個箭頭都有唯一的後繼箭頭,這就可以允許我們使用暴力倍增來算了,具體實現細節太過繁瑣,不過確實是一道很鍛鍊綜合能力的題目。


https://github.com/becauseofyou/Contests/tree/master/Codeforces/ABBYY_3.0_final

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章