標籤:數學 類比
文章被盜還是很嚴重,加著作權資訊
轉載請註明出處 [ametake著作權]http://blog.csdn.net/ametake歡迎來看看
題目:
題目描述 Description
有一個無窮序列如下: 110100100010000100000… 請你找出這個無窮序列中指定位置上的數字
輸入描述 Input Description
第一行一個正整數N,表示詢問次數; 接下來的N行每行一個正整數Ai,Ai表示在序列中的位置。
輸出描述 Output Description
N行,每行為0或1,表示序列第Ai位上的數字。
範例輸入 Sample Input
4
3
14
7
6
範例輸出 Sample Output
0
0
1
0
資料範圍及提示 Data Size & Hint
【資料範圍】 對於100%的資料有N≤1500000,Ai≤10^9
我們觀察序列,發現這個序列可以分為很多組,每一組為1和很多0 0的個數取決於他前面的1是第幾個1
這道題目有好多做法,看資料規模,單個查詢必須是O(1)的時間 但本體資料相當弱= =
先放上我自己的做法,和題解裡一位同學是相似的,用類比。
剛開始想的是儲存每個位置上的數字直接查表,但顯然空間不足。256M可以開一億的數組,但本題需要十億= =
所以改為用數組f[i]表示第i個1的位置 這樣只需要五萬左右 五萬平方就是二十五億了
之後對於每個詢問尋找有沒有i使得f[i]==x即可
尋找可以最佳化,最佳化為二分,還有更快的,利用每個1的位置都是n*(n+1)/2 將尋找範圍縮小為幾個數
但是我的最佳化失敗了= =好在資料很弱,從1到maxn尋找就可以過
上代碼
顯然此題還有更多更好的做法,我來總結一下:
1.裡奧的做法,直接解方程n*(n+1)/2=x的整數解 如果有就是1 否則是0
2.這種方法我不大理解
”判斷8*a-7是否為完全平方數即可
即是否trunc(sqrt(8*a-7))=sqrt(8*a-7)“
3.一種數論方法:
只要求出距離k最近的1所在位置即可
不難發現 每一個出現1位置都符合n*(n+1)/2+1,於是進行以下推導:
設k=n*(n+1)/2(n為最近的1所在位置,k為詢問的位元
則有2*k=n*(n+1)
可見n=trunc(sqrt(n*(n+1)))=trunc(sqrt(2*k))
求出n後只要判斷k是否等於n*(n+1)/2+1即可
t:=trunc(sqrt(2*k));
if k<>(t*t+t) div 2+1 then
ans[i]:=0
else
ans[i]:=1;
有的地方不大懂 尤其是取整這裡 trunc是去尾
4.另一種數論 與上方類似,但也有一段不大理解
假設我們遇到了一個輸入n,並假設它處於第m組。
於是:0.5*(m-1)*m<n<=0.5*m*(m+1)
上式乘2,得到:m*(m-1)<2n<=m*(m+1)
放縮,得到:(m-1)*(m-1)<2n<(m+1)*(m+1)
這樣,我們就只需要將2n開方再取整,那麼得到的數字要麼是m,要麼是m-1,進行一下判斷就可以輕鬆的求解出m
而m正好就是n在的組數!
這樣,我們就用O(1)的方法求出了n在的組數。秒殺掉此題。
好吧,膜拜上面諸大神,題解多來自codevs
於是這道題就這麼結束了 下午還是要加油啊
——溪雲初起日沉閣,山雨欲來風滿樓。
文章被盜還是很嚴重,加著作權資訊
轉載請註明出處 [ametake著作權]http://blog.csdn.net/ametake歡迎來看看
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
【基礎練習】【數論/類比】codevs1670 無窮的序列題解