# 求 0~n 當中有幾個數字 $k(0 \le k \le 9)$
### 想法 :
若 $k=0$ ,則要分開討論
#### **1.** $k=0$
我們逐位討論,每一次將數字分為 $cur,$ $high,$ $low$ ,分別是現在這一位數,在他左邊的數,以及在他右邊的數。
以 $1034$ 為例:
$\;\;\;$ 第一次進入迴圈時 $high=103,$ $cur=4,$ $low=0,$ $base=1$。
$\;\;\;$ 因為 $cur \ne 0$ ,因此會有 $10,20,30...1030$ ,共 $103$ 個 $0$。
$\;\;\;$ 第二次進入迴圈時 $high=10\;\;,$ $cur=3,$ $low=4,$ $base=10$。
$\;\;\;$ 同樣因 $cur \ne 0$ ,因此會有 $100,101,102...300...1000$ ,共 $100$ 個 $0$。
$\;\;\;$ 第三次進入迴圈時 $high=1\;\;\;\;,$ $cur=0,$ $low=34,$ $base=100$。
$\;\;\;$ 這次 $cur=0$ ,因此會有 $1000,1001,1002...1034$ ,共 $35$ 個 $0$
最後不要忘記還有 $0$ 本身也是一個。
#### **2.** $k>0$
同樣逐位討論,每一次將數字分為 $cur,$ $high,$ $low$ ,分別是現在這一位數,在他左邊的數,以及在他右邊的數。
以 $n=1034,\;k=2$ 為例:
$\;\;\;$ 第一次進入迴圈時 $high=103,$ $cur=4,$ $low=0,$ $base=1$。
$\;\;\;$ 因為 $cur > k$ ,因此會有 $2,12,22,32...1032$ ,共 $104$ 個 $2$。
$\;\;\;$ 第二次進入迴圈時 $high=10\;\;,$ $cur=3,$ $low=4,$ $base=10$。
$\;\;\;$ 同樣因 $cur > k$ ,因此會有 $20,21,22,23...320...1020$ ,共 $110$ 個 $2$。
$\;\;\;$ 第三次進入迴圈時 $high=1\;\;\;\;,$ $cur=0,$ $low=34,$ $base=100$。
$\;\;\;$ 這次 $cur < k$ ,因此會有 $200,201,202...299$ ,共 $100$ 個 $2$
### 實作 :
```cpp=
// just for 0
ll countDigit(ll n){
if(n<1) return 1;
ll high=n,tp=0,cur=0,low=0,base=1,ret=0;
while(high>0){
high=n/(10*base);
tp=n%(10*base);
cur=tp/base;
low=tp%base;
if(cur==0){
ret+=(high-1)*base+low+1;
}else{
ret+=high*base;
}
base*=10;
}
return ret+1;
}
// only for 1~9
ll countDigit(ll n,ll k){
if(k==0) return countDigit(n);
ll high=n,tp=0,cur=0,low=0,base=1,ret=0;
while(high>0){
high=n/(10*base);
tp=n%(10*base);
cur=tp/base;
low=tp%base;
if(cur==k){
ret+=high*base+low+1;
}else if(cur<k){
ret+=high*base;
}else{
ret+=(high+1)*base;
}
base*=10;
}
return ret;
}
```
###### tags: `程式設計`