給定一個整數N,表明N個盒子。第i個盒子當中有i個球。ios
咱們能夠選定一個N之內的天然數X,多多雞會把全部盒中小球數量大於X的盒子減小X個球。如今想要用最少的步驟將全部盒子的球清空,請問最少須要多少次操做?算法
第一行輸入一個整數t,表示測試組數。數組
對於每一行都輸入一個整數N()函數
要求對於每組數據輸出一個整數做爲結果。測試
咱們仔細分析一下,會發現這題的難點有兩個。第一個是這個N的範圍太大了,對咱們的複雜度限制得很高。第二點是盒子當中球的數量是動態的,在如此苛刻的複雜度要求下,咱們很難掌握全部盒子的動態。spa
但若是你有足夠多經驗的話,會發現N的範圍其實並非限制而是提示。N的範圍達到1e9,在這個量級下咱們連的計算都是會超時的,也就是說全部須要遍歷盒子的算法均可以放棄了,看似苛刻,其實會節省咱們不少時間。若是N的範圍給個1e6,那纔是真的噁心。估計不少同窗要被騙了,苦苦思考怎麼樣經過模擬的方法來計算。code
既然範圍是1e9,那麼沒的說,這題必定是經過一些巧妙的方法來計算的。可是到底是什麼巧妙的方法,咱們幹想是想不出來的,要想知道也不難,嘗試着去作一下就能夠找到門道了。blog
咱們假設咱們第一次選擇了k,也就是序號大於等於k的盒子裏球的數量都減小了k。那麼減小以後的狀況變成什麼樣了呢?咱們列出來看看:。rem
有些同窗看到這個可能會想第二個數字選什麼,若是你這麼想了,可能你作的題目還不夠多,不夠敏感。其實看到這個已經能夠發現,當咱們選擇了k以後,數組被拆分紅了兩個部分,左邊是0到k-1,右邊是1到N-k,中間0是分割線。string
這一點發現有什麼用呢?其實頗有用,咱們首先來作一個假設,假設k-1 > N-k,也就是左邊部分的元素比右邊更多。那麼無論咱們接下來如何操做,其實只要咱們的操做可以消除掉左邊的部分,右邊的天然也會跟着消除。同理,若是k-1 < N-k,也是同樣的。因此咱們經過選擇了k以後,數組拆分紅了兩個部分,答案只和其中的一個部分有關,而且是和其中元素最多的部分有關。
那麼根據這一點,咱們能夠直接寫出表達式來表示N時的答案:
這個式子看起來很複雜不知道如何解,但其實也很簡單,咱們還有一個條件沒有用上。就是f必然是一個遞增函數,這個其實不須要嚴格證實,咱們直觀上就能夠感覺出來。既然f是遞增函數,那麼上面式子當中不少元素的大小關係就都明顯了。
這樣遞推式就出來了,咱們接下來要作的就是根據這個遞推式寫出它的通項。
咱們把上面的式子所有累加在一塊兒,右邊帶有f的項會被所有消掉,最終獲得:。這個表達式有了,那麼代碼天然手到擒來。
#include <iostream> #include <cstdio> #include <cstring> #include <queue> #include <vector> #include <cmath> #include <cstdlib> #include <string> #include <map> #include <set> #include <algorithm> #include "time.h" #include <functional> #define rep(i,a,b) for (int i=a;i<b;i++) #define Rep(i,a,b) for (int i=a;i>=b;i--) #define foreach(e,x) for (__typeof(x.begin()) e=x.begin();e!=x.end();e++) #define mid ((l+r)>>1) #define lson (k<<1) #define rson (k<<1|1) #define MEM(a,x) memset(a,x,sizeof a) #define L ch[r][0] #define R ch[r][1] using namespace std; const int N=1000050; const long long Mod=1000000007; int t, x; int main() { scanf("%d", &t); rep(z, 0, t) { scanf("%d", &x); printf("%dn", int(log(x)/log(2)) + 1); } return 0; }
這道題從難度上來說其實不大,可是真正在筆試的過程中遇到,估計不少同窗可能作不出來。倒不是由於算法有多難,而是會一開始的時候就走了歪路,好比去思考怎麼樣選擇k,好比去想遞推的解法等等。這種對問題的敏感和思路是須要練習的,並非看幾篇文章或者是聽聽大牛講課就能夠得到的。
通常公司的筆試題不會很難,每每都是這種須要縝密思考的思惟題,這種題多作多練很容易就摸到套路了。若是對這些問題感興趣能夠看看codeforces專題,裏面有不少有趣的思惟題。好了,今日分享到這就結束了,喜歡能夠點個關注哦。