1. 程式人生 > >整數中1出現的次數(從1到n整數中1出現的次數)

整數中1出現的次數(從1到n整數中1出現的次數)

blank 特殊情況 你們 描述 允許 acm terminal cell des

題目描述

求出1~13的整數中1出現的次數,並算出100~1300的整數中1出現的次數?為此他特別數了一下1~13中包含1的數字有1、10、11、12、13因此共出現6次,但是對於後面問題他就沒轍了。ACMer希望你們幫幫他,並把問題更加普遍化,可以很快的求出任意非負整數區間中1出現的次數(從1 到 n 中1出現的次數)。

當n = 3141592時:

<thead></thead>
mabones
1 3141592 0 (3141592+8)/10*1+0=314160
10 314159 2 (314159+8)/10*10+0=314160
100 31415 92 (31415+8)/10*100+0=314200
1000 3141 592 (3141+8)/101000+1(592+1)=314593

當然後面還有m=10000,100000,1000000三種情況,對應著萬位,十萬位, 百萬位為1時的情況

下面說下a+8的意義:

當考慮個位,十位,百位這三位為1的情況時:

個位 2 ,當個位取值1時,前面的六位數字可由0~314159組成,即314160種情況

十位9,當十位取值1時,前面的五位數字可由0~31415組成,十位之後的一位可由0~9組成,組合情況31416*10=314160種情況

百位5,當百位取值為1時,前面的四位數字可由0~3141組成,百位之後的兩位可由0~99組成,組合情況為3142*100=314200種情況


註意:當考慮千位1時:

千位1,千位取值即1,前面的三位數字可由0~314組成,但是當前面的值為314時,後面的三位只有0~592種情況(特殊情況),其余的情況即為前面的值為0~313,後面三位有0~999,情況數為3141000,所以總情況數為3141000 + 593=314593種情況

這時可發現和代碼中的公式算的情況是吻合的,a+8的巧妙之處在於當a的最後一位(當前分析位)為0或1時,加8不產生進位,這是為需要單獨算的特殊情況做準備,而當前分析位為2~9時,不需要考慮特殊情況,所以允許加8產生的進位。

鏈接:https://www.nowcoder.com/questionTerminal/bd7f978302044eee894445e244c7eee6

來源:牛客網

int countDigitOne(int n) {
    int ones = 0;
    for (long long m = 1; m <= n; m *= 10) {
        int a = n/m, b = n%m;
        ones += (a + 8) / 10 * m + (a % 10 == 1) * (b + 1);
    }
    return ones;
}

整數中1出現的次數(從1到n整數中1出現的次數)