問題描述
給定一個十進制整數N,求出從1到N的所有整數中出現”1”的個數。
例如:N=2時 1,2出現了1個 “1” 。
N=12時 1,2,3,4,5,6,7,8,9,10,11,12。出現了5個“1”。
方法一 暴力求解
最直接的方法就是從1開始遍歷到N,將其中每一個數中含有“1”的個數加起來,就得到了問題的解。
下面給出代碼:
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 int main() 5 { 6 int n,x,t; 7 while(scanf("%d",&n)!=EOF) 8 { 9 int ans=0; 10 for(int i=1;i<=n;i++) 11 { 12 t=i; 13 while(t) 14 { 15 if(t%10==1) 16 ++ans; 17 t=t/10; 18 } 19 } 20 printf("%d\n",ans); 21 } 22 return 0; 23 }
該算法的時間復雜度為O(N*lgN)
(注:此方法對較大的數據有可能會TL)
解法二
1位數的情況:
在解法二中已經分析過,大於等於1的時候,有1個,小於1就沒有。
2位數的情況:
N=13,個位數出現的1的次數為2,分別為1和11,十位數出現1的次數為4,分別為10,11,12,13,所以f(N) = 2+4。
N=23,個位數出現的1的次數為3,分別為1,11,21,十位數出現1的次數為10,分別為10~19,f(N)=3+10。
由此我們發現,個位數出現1的次數不僅和個位數有關,和十位數也有關,如果個位數大於等於1,則個位數出現1的次數為十位數的數字加1;如果個位數為0,個位數出現1的次數等於十位數數字。而十位數上出現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~123
我們可以繼續分析4位數,5位數,推導出下面一般情況:
假設N,我們要計算百位上出現1的次數,將由三部分決定:百位上的數字,百位以上的數字,百位一下的數字。
如果百位上的數字為0,則百位上出現1的次數僅由更高位決定,比如12013,百位出現1的情況為100~199,1100~1199,2100~2199,…,11100~11199,共1200個。等於更高位數字乘以當前位數,即12 * 100。
如果百位上的數字大於1,則百位上出現1的次數僅由更高位決定,比如12213,百位出現1的情況為100~199,1100~1199,2100~2199,…,11100~11199,12100~12199共1300個。等於更高位數字加1乘以當前位數,即(12 + 1)*100。
如果百位上的數字為1,則百位上出現1的次數不僅受更高位影響,還受低位影響。例如12113,受高位影響出現1的情況:100~199,1100~1199,2100~2199,…,11100~11199,共1200個,但它還受低位影響,出現1的情況是12100~12113,共114個,等於低位數字113+1。
綜合以上分析,寫出如下代碼:
1 #include<iostream> 2 #include<cstdio> 3 #include<map> 4 #include<cstring> 5 #include<string> 6 #include<algorithm> 7 #include<queue> 8 #include<vector> 9 #include<stack> 10 #include<cstdlib> 11 #include<cctype> 12 #include<cmath> 13 #define LL long long 14 using namespace std; 15 int CountOne(int n) { 16 int cnt = 0; 17 int i = 1; 18 int current = 0, after = 0, before = 0; 19 while ((n / i) != 0) { 20 current = (n / i) % 10; 21 before = n / (i * 10); 22 after = n - (n / i) * i; 23 if (current > 1) 24 cnt = cnt + (before + 1) * i; 25 else if (current == 0) 26 cnt = cnt + before * i; 27 else if (current == 1) 28 cnt = cnt + before * i + after + 1; 29 i = i * 10; 30 } 31 return cnt; 32 } 33 int main() 34 { 35 int n; 36 while(cin>>n){ 37 int res=CountOne(n); 38 cout<<res<<endl; 39 } 40 return 0; 41 }