/*
1的數目:
給定乙個十進位制正整數n,寫下從1開始,到n的所有整數然後數一下其中出現的所有1的個數
例如:n=2,寫下1,2這樣只出現了1個1
n=12,寫下1,2,3,4,5,6,7,8,9,10,11,12,這樣1的個數是5
問題是:
1寫乙個函式f(n),返回1到n之間出現的1的個數,比如f(12) = 5,
2滿足條件f(n) = n的最大n是多少?
劍指解法:
需要用遞迴,拆分成三部分:最高位是1 + 除最高位剩餘的位數的1 + 遞迴的1
最高位不是1
解法1:
從1開始遍歷到n,將其中的每乙個數含有1的個數加起來,
解法2:
給定n,分析小於n的數在每一位上可能出現1的次數之和來得到這個結果,對於乙個特定的n,分析其中規律:
先看1位數的情況:
如果n=3,那麼從1到3的數字是:1,2,3,只有個位數字上可能出現1,而且只出現1次,進一步可以發現如果n是個位數,且n>=1,那麼f(n)都等於1
規律:如果n是個位數,且n>=1,f(n) = 1,如果n=0,f(0) = 0
再看兩位數的情況:
如果n=13,那麼從1到13所有數字為:1,2,3,4,5,6,7,8,9,10,11,12,13,個位和十位的數字上都可能是1。個位出現1的次數有兩次:1和11
十位出現1的次數有4次:10,11,12,13,所以f(n) = 2 + 4 = 6.11這個數字個位和十位都是1,但是11恰好被計算了兩次。
n=23,十位出現1的次數為10次,從10~19,個位出現1的次數為1,11,21,所以f(23) = 10 + 3 = 13
個位數出現1的次數不僅和個位數字有關,還和10位數字有關;如果n的個位數》=1,則個位出現1的次數為十位數的數字加1
= 0,則個位出現1的次數為十位數的數字
十位數=1,則十位數上出現1的次數為個位數的數字加1
十位數》1,則十位數上出現1的次數為10
分析3位數:
n=123
個位出現1的個數為13:1,11,21,...,91,101,111,121
十位出現1的個數為20:10~19,110~119
百位出現1的個數為24:100~23
假設n=abcde,這裡a,b,c,d,e分別是十進位制數n的各個數字上的數字。如果要計算百位上出現1的次數,它收到3個因素的影響,百位上的數字,百位以下,百位以上
如果百位 = 0,百位上出現1的次數由更高位決定:比如12013,百位出現1的情況可能是100~199,1100~1199,2100~2199,。。。,11100~11199,一共有1200個
由更高位的數字12*當前位數100
如果百位上的數字為1,百位出現1的次數不僅受更高位影響,還受低位影響,比如12113,受更高位影響,百位出現1的情況時100~199,1100~1199,2100~2199,。。。,
11100~11199,gong 1200個,等於更高位數字12*當前位數。
受低位影響,百位出現1的情況時12100~12113,等於低位數字113+1
如果百位上數字大於1(即為2~9),則百位上出現1的次數僅由更高位決定,比如12213,則百位上出現1的可能性為:100~199,1100~1199,2100~2199,...,11100~11199,
12100~12199共1300個。=更高位數字加1*當前位數= (12+1)*100
問題2的解法:
要確定最大的數n,滿足f(n) = n,分析
9以下為:1個
99以下為:10*1 + 10*1 = 20
999以下為:(99+1)*1 + (9+1)*10 + (0+1)*100 = 100 + 100 + 100 = 300
9999以下為:(0+1)*1000+10*300 = 4000
999 999 999 以下為:900 000 000個
9 999 999 999 以下為:10 000 000 000個
歸納得:f(10^n-1) = n*10^(n-1)
當n>10^10 - 1,f(n)的值大於n,可以猜想,當n大於某乙個數n時,f(n)會始終比n大,也就是說最大滿足條件在0~n之間,如果能估計出這個n,只要讓n從n往0遞減,
第乙個滿足的的數就是要求的整數
問題轉化為如何證明上界n存在,並估計該上界n。
令n=10^11-1=99 999 999 999,讓n從n往0遞減,依次檢查是否有f(n) = n,第乙個滿足條件的就是我們要找的整數。得出n = 1 111 111 110,是滿足f(n) =n的最大整數
輸入:2
1223
123輸出:15
1357
*//*
關鍵:1 llow = n - (n/lfactor)*lfactor;//參見123 - (123/10)*10
lcur = (n / lfactor) % 10;//參見(123/10)%10
lhigh = n / (lfactor * 10);//參見123 / (10*10)
2 case 0: lcount += lhigh * lfactor;//如果當前位為0,那麼當前位出現1的次數 = 高位*位數
break;
case 1: lcount += lhigh * lfactor + llow + 1;//如果當前位為1,那麼當前位出現1的次數 = 高位 * 位數 + 低位 + 1
break;
default: lcount += (lhigh + 1) * lfactor;//如果當前位》=2,那麼當前為出現1的次數 = (高位+1)*位數
3 當n>10^10 - 1,f(n)的值大於n,可以猜想,當n大於某乙個數n時,f(n)會始終比n大,也就是說最大滿足條件在0~n之間,如果能估計出這個n,只要讓n從n往0遞減,
第乙個滿足的的數就是要求的整數
問題轉化為如何證明上界n存在,並估計該上界n。
令n=10^11-1=99 999 999 999,讓n從n往0遞減,依次檢查是否有f(n) = n,第乙個滿足條件的就是我們要找的整數。得出n = 1 111 111 110,是滿足f(n) =n的最大整數
long long ln = 1e11 - 1;
*/#include int count1(int n)
while(n);
return iret;
}long long count1_divide(int n)
lfactor *= 10;
} return lcount;
}long long findn()
ln--; }
}void process()
//printf("%d\n",iret);
printf("%lld\n",count1_divide(n)); }}
void process2()
int main(int argc,char* argv)
程式設計之美 第二章 數字之魅 2 3尋找發帖水王
尋找發帖水王 本質 尋找出現超過一半次數的人 如果已經排序,那麼中序數就是那個人,即下標是,這個列表的第n 2項是 從0開始編號 如果每次刪除兩個不同的id,可以降低時間複雜度 輸入 7 1 2 3 2 4 2 2 81 2 3 2 4 2 2 5 輸出 2 沒有 include const int...
程式設計之美 第二章 數字之魅 2 5尋找最大的k個數
尋找最大的k個數 解法1 如何避免對後n k個數的排序,選擇排序和交換排序都是不錯的選擇,o n k 如果k log2n時,那麼可以選擇部分排序。解法三 尋找n個數中最大的k個數,本質就是尋找最大的k個數中最小的那個,也就是第k大的數。可以使用二分搜尋,對於乙個給定的數p,可以在o n 的時間複雜度...
第二章 程式設計之道
程式設計師的修煉從優秀帶卓越 第二章 程式設計之道 切記一根筋 優秀的開發者和平庸的開發者之間存在著的一條鴻溝,因為優秀的程式設計師所具有的的素質似乎是與生俱來。那麼成為優秀的程式設計師的方法是拋開程式設計,放下編譯器,好好的評估一下自己正在做的事情。你必須培養自己對於程式設計周邊所有事情的熱情。你...