[BZOJ3613][Heoi2014]南園滿地堆輕絮 二分答案
阿新 • • 發佈:2018-09-27
out 遞推 fine 最大 愛好者 pre zoj ace amp
3 815 6901 3839 178 199 10007
199 4568 1901,此時將 4568 修改為 3234,1901 也修改為 3234 即可,代價為 1334。
Description
小 Z 是 ZRP(Zombies’ Republic of Poetry,僵屍詩歌共和國)的一名詩歌愛好者,最近 他研究起了詩詞音律的問題。 在過去,詩詞是需要編成曲子唱出來的,比如下面這首《菩薩蠻》,唱出來的話其對應 的音符就是這樣的: 南 園 滿 地 堆 輕 絮, 愁 聞 一 霎 清 明 雨 1 1 5 5 6 6 5 4 4 3 3 2 2 1 因而可以發現,“1 1 5 5 6 6 5 4 4 3 3 2 2 1”這串音符就成為了研究音律的關鍵。 小 Z 翻閱了眾多史料發現,過去的一首曲子的音調是不下降的 小 Z 想要知道對於一首給定的曲子,如何通過提高音調或者降低音調,將它的音調修改 的不下降, 而且使得修改幅度最大的那個音符的修改幅度盡量小。 即如果把一個包含 n 個音 符的曲子看做是一個正整數數列 A[1]…A[n], 那麽 目標是求另一個正整數數列 B[1]…B[n], 使得對於任意的 1≤i<n 有 B[i] ≤B[i+1], 而且使得 Ans = Max{|A[j]-B[j]|,1≤j≤n}盡量 小。 小 Z 很快就想清楚了做法,但是鑒於他還忙著寫詩, 所以這個任務就交給了你。Input
由於數據規模可能較大,因此采用如下方式生成數據。
每個數據包含 6 個數:n,Sa,Sb,Sc,Sd,A[1],Mod,意為共有 n 個音符,第一個音符為 A[1]。 生成規則如下: 定義生成函數 F(x) = Sa*x^3 + Sb*x^2 + Sc*x + Sd; 那麽給出遞推公式 A[i] = F(A[i-1]) + F(A[i-2]),此處規定 A[0] = 0. 由於中間過程的數可能會特別大,所以要求每一步與 A 中的每個數都對一個給定的數 Mod 取模。Output
輸出一行,包含一個正整數 Ans。
Sample Input
Sample Output
1334HINT
n≤5000000
對於 100%的數據, Sa,Sb,Sc,Sd,A[1] ≤10000, Mod≤1000000007 樣例中生成的數列為:199 4568 1901,此時將 4568 修改為 3234,1901 也修改為 3234 即可,代價為 1334。
Solution
二分答案暴力判斷啊...
二分最後的答案,$check$的時候更新一個$max(a[i]-x,mx)$,如果$a[i]+x$都比目前的$mx$小的話顯然就無法構成不下降序列了
還有一點就是一定要註意乘法的溢出,$1ll$和$mod$要多用幾個
#include <cstdio> #include <algorithm> #include <cstring> using namespace std ; #define N 5000010 int n , sa , sb , sc ,sd , mod ; int a[ N ] ; int F( int x ) { return ( ( ( 1ll * sa * x % mod * x % mod * x % mod + 1ll * sb * x % mod * x % mod ) % mod + 1ll * sc * x % mod ) % mod + 1ll * sd % mod ) % mod ; } bool check( int x ) { int mx = 0 ; for( int i = 1 ; i <= n ; i ++ ) { mx = std::max( mx , a[ i ] - x ) ; if( a[ i ] + x < mx ) return 0 ; } return 1 ; } int main() { scanf( "%d%d%d%d%d%d%d" , &n , &sa , &sb , &sc , &sd , &a[ 1 ] , &mod ) ; a[ 0 ] = 0 ; for( int i = 2 ; i <= n ; i ++ ) { a[ i ] = F( a[ i - 1 ] ) + F( a[ i - 2 ] ) ; a[ i ] = a[ i ] % mod ; } int l = 0 , r = mod , ans = mod ; while( l <= r ) { int mid = ( l + r ) >> 1 ; if( check( mid ) ) r = mid - 1 , ans = mid ; else l = mid + 1 ; } printf( "%d\n" , ans ) ; }
[BZOJ3613][Heoi2014]南園滿地堆輕絮 二分答案