數列

前言
“從正面看,是偉大的神(God);從反面看,是卑鄙小人(dog)。其實,人們所犯的罪惡(evil),反過來,正是爲了活着(live)。”歡迎來到嘟嘟課堂。今天我們講一道看似特別特別水一看數據範圍限制嚇你一跳的題——數列!
題目描述
Smart非常喜歡研究數列規律,一天他在紙上寫着一列數:1,2,3,…,N,突然他想到:1,2,3,…,N這些數裏面,1出現的次數是多少?如N=11的時候,有1, 10, 11共出現4次1。
現在告訴你N,你能幫助Smart快速給出答案麼?
輸入
第一行包括一個整數N。
輸出
輸出一行一個整數,表示這個數列1~N中1出現的次數。
樣例輸入
11
樣例輸出
4
數據範圍限制
30%的數據:1≤N≤200;
100%的數據:1≤N≤2*10^8。
思路
這道題相信大家一看到題目描述就覺得水的不得了,但是一看數據範圍限制就會嚇一大跳,連O(n)的方法都過不了。這就是一道經典的數論題。那麼這時候我們就要找規律,簡化一下程序:
個位的1:N div 10+如果n mod 10 >0就是1,否則是0
十位的1:N div 100*10+min(N mod 100,19)-9
百位的1:N div 1000*100+min(N mod 1000,199)-99
……
以此類推,我們可以得到一條公式。
if (i mod 10=1) then inc(ans,i div 10*k+n mod k+1)
else if (i mod 10=0) then inc(ans,i div 10*k)
else inc(ans,(i div 10+1)*k);
不懂的童鞋可以自己多理解幾次,其實就是一道小學奧數題。還是不懂的可以去了解一下小學的數論。
代碼

var
        i,k,n,ans:int64;
begin
        readln(n);
        k:=1;
        while n>=k do
        begin
                i:=n div k;
                if (i mod 10=1) then inc(ans,i div 10*k+n mod k+1)
                        else if (i mod 10=0) then inc(ans,i div 10*k)
                                else inc(ans,(i div 10+1)*k);
                k:=k*10;
        end;
        writeln(ans);
end.
發佈了76 篇原創文章 · 獲贊 90 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章