dp P1982 小朋友的數字

2022-05-20 05:44:10 字數 1601 閱讀 6376

有趣的細節題目

有 n 個小朋友排成一列。每個小朋友手上都有乙個數字,這個數字可正可負。規定每個小朋友的特徵值等於排在他前面(包括他本人)的小朋友中連續若干個(最少有乙個)小朋友手上的數字之和的最大值。

作為這些小朋友的老師,你需要給每個小朋友乙個分數,分數是這樣規定的:第乙個小朋友的分數是他的特徵值,其它小朋友的分數為排在他前面的所有小朋友中(不包括他本人),小朋友分數加上其特徵值的最大值。

請計算所有小朋友分數的最大值,輸出時保持最大值的符號,將其絕對值對 p 取模後輸出。

對於 100%的資料,1 ≤ n ≤ 1,000,000,1 ≤ p ≤ 10^9,其他數字的絕對值均不超過 10^9。

求的就是1.特徵值 2.分數。

特徵值:

演算法一:

靜態字首和。

直接列舉出所有的情況(兩字首和之差就是一段區間的sum值),取max。順便取一下

因為當前這一位存在意義就是它被取為最大區間的值,否則就應當取之前的special值,以維持它的不下降性質。但是如果想把這種思路優化到

的話,是不可以的。例如這組資料:「3 -2 3」,value[2]對於special[1]是沒有意義的,但是value[1]+value[2]>0故對於special[3]有意義。

由此引申到演算法二

演算法二:

這是乙個假演算法:看做很多個子段和,還有分開的字首和,但是不能保證每乙個值是前面的最大值

演算法三:

這不就是最大子段和的入門題嗎(某年初賽題)然後再維持一下最大值以及順序賦值就可以了

分數:由題面可以得到

;。並且在

中維持不下降的性質(當

時,答案可能是

;當,答案必為

)。那麼就容易得到

。因為計算過程中有可能爆精度,但又不能馬上模,一種是c++中__int128,另一種是當

時就能確定

(但是!但是!這個方法雖然被很多ac資料採用,但是遇到如:8 66 -511657297 151810723 -588294472 -271526366 58051666 -792123397 -76376854 -36217375 此資料時會計算出錯誤答案!)。如果堅持正解的話,還是用大整數或者__int128(c++)吧。

那麼怎麼計算

呢?題目的計算方法是

我們可以發現,

所以當計算

時,我們只需要比較

與,即看

的正負同樣的,我們需要維持這個序列的不下降性。於是就過了。

「將其絕對值對 p 取模後輸出」我是先取絕對值,再按原符號not x + 1 (get到了轉相反數的位運算)

另外,模數是個麻煩的問題。最早的時候,我是輸入就模、計算就模,但是我忽略了乙個非常明顯的問題:最大值模後不一定最大,就是說這樣計算出來的只是模後最大值。所以用以上的「另一種」方法,在確定

後開始模數(於是就和大部分程式一樣實際上不完全正確;但本題luogu資料(也許就是當年資料)真的非常不全面,就算很多小細節沒有完全也能ac)

還有一件事:pas裡面longint溢位沒有報re!90分的最後乙個點wa就是因為溢位到負數!這操作很神奇

精簡後的**框架就是這樣子的

P1982 小朋友的數字

有 nn個小朋友排成一列。每個小朋友手上都有乙個數字,這個數字可正可負。規定每個小朋友的特徵值等於排在他前面 包括他本人 的小朋友中連續若干個 最少有乙個 小朋友手上的數字之和的最大值。作為這些小朋友的老師,你需要給每個小朋友乙個分數,分數是這樣規定的 第乙個小朋友的分數是他的特徵值,其它小朋友的分...

題解 P1982 小朋友的數字

題目鏈結 題目大意 求 max 其中 f i max d j 表示區間 1,j 內的最大連續子段和 動態規劃 分析 看了題目題目大意,這題顯然還是挺水的吧.我們先看狀態 d 怎麼求 我們設 td i 表示以 i 結尾的最大連續子段和,那麼顯然 td i max td i 1 val i val i ...

洛谷P1982 小朋友的數字

有 n 個小朋友排成一列。每個小朋友手上都有乙個數字,這個數字可正可負。規定每個小朋友的特徵值等於排在他前面 包括他本人 的小朋友中連續若干個 最少有乙個 小朋友手上的數字之和的最大值。作為這些小朋友的老師,你需要給每個小朋友乙個分數,分數是這樣規定的 第乙個小朋友的分數是他的特徵值,其它小朋友的分...