1049 Counting Ones (30 point(s)) - C語言 PAT 甲級

1049 Counting Ones (30 point(s))

The task is simple: given any positive integer N, you are supposed to count the total number of 1’s in the decimal form of the integers from 1 to N. For example, given N being 12, there are five 1’s in 1, 10, 11, and 12.

Input Specification:

Each input file contains one test case which gives the positive N (≤ 230).

Output Specification:

For each test case, print the number of 1’s in one line.

Sample Input:

12

Sample Output:

5

題目大意:

給一個數字 N,求 1 - N 數字中出現的 1 的數量

例如所給數字 12,則 1 - 12 中 1 出現的個數爲 5 個,分別出現在 1,10,11,12 中

設計思路:

可以看作數學的排列組合問題,遍歷計算每一位上 1 出現的次數並相加

  • 遍歷到每一位,分爲三個部分,當前位的數值 now,左側數值 left,右側數值 right,now 在個位 i = 1,now 在十位 i = 10,now 在百位 i = 100……依次類推,則:
    • now == 0: count += (left * i);
    • now == 1: count += (left * i) + (right + 1);
    • now >= 2: count += (left * i) + (i);

例如:501255

  • 遍歷到百位時 now >= 2,則原數分爲 left=501 2 55=right,將百位置爲 1,
    • left=[0, 500] 1 [0, 99]=right,當 left=[0, 500] 任一值時,右側可以 right=[0, 99] 中任一值
    • left=501 1 [0, 99]=right,當 left=501 時,右側依舊可以 right=[0, 99] 中任一值而小於原數
    • 排列組合爲 (501 X 100) + (100) = 50200
  • 遍歷到千位時 now == 1,則原數分爲 left=50 1 255=right,將千位置爲 1,
    • left=[0, 49] 1 [0, 999]=right,當 left=[0, 49] 任一值時,右側可以 right=[0, 999] 中任一值
    • left=50 1 [0, 255]=right,當 left=50 時,右側僅可以 right=[0, 255] 中任一值而小於原數
    • 排列組合爲 (50 X 1000) + (255 + 1) = 50256
  • 遍歷到萬位時 now == 0,則原數分爲 left=5 0 1255=right,將萬位置爲 1,
    • left=[0, 4] 1 [0, 9999]=right當 left=[0, 4] 任一值時,右側可以 right=[0, 9999] 中任一值
    • left=5 1 null=right,當 left=5 時,大於原數,右側無法填入任何值
    • 排列組合爲 (5 X 10000) + 0 = 50000
  • 歸納總結即可得上方結論。同理,
    • 遍歷到個位時,原數分爲 left=50125 5 null=right,排列組合爲 (50125 X 1) + (1) = 50126,
    • 遍歷到十位時,原數分爲 left=5012 5 5=right,排列組合爲 (5012 X 10) + (10) = 50130,
    • 遍歷到十萬位,原數分爲 left=null 5 01255=right,排列組合爲 (0 X 100000) + (100000) = 100000,
    • 最終相加結果爲 350712
編譯器:C (gcc)
#include <stdio.h>

int main(void)
{
        int n;
        int count = 0, left = 0, now = 0, right = 0;
        int i;

        scanf("%d", &n);
        for (i = 1; n / i; i *= 10) {
                left = n / (i * 10);
                now = n / i % 10;
                right = n % i;
                if (now == 0) {
                        count += (left * i);
                } else if (now == 1) {
                        count += (left * i + right + 1);
                } else {
                        count += (left * i + i);
                }
        }
        printf("%d", count);

        return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章