PAT 解题报告 1049. Counting Ones (30)

1049. Counting Ones (30)

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(<=230),要求计算所有小于 N 的正整数的各个位置上,1 出现的次数之和。

分析

比较有思维难度的一题,核心在于找规律。10ms 的时间限制表明了不能用常规的循环遍历来解决。需要从简单的 case 找规律,逐步扩大到常规的情况。

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <cmath>
#include <algorithm>
//规律0~9有1个1;0~99有20个1;0~999有300个1...
using namespace std;
#define UP 10
int a[UP] = {0};
void mka(){
    for (int i=1; i<UP; i++) {
        double tmp = pow(10, i-1);
        a[i] = tmp * i;
    }
}
int getD(int n) {//得出几位数,123是3位数
    int cnt = 0;
    while (n!=0) {
        n/=10;
        cnt++;
    }
    return cnt;
}

int main()
{
    mka();
    int N;
    scanf("%d", &N);
    int sum = 0;
    while (N !=0 ) {//每次循环处理最高位
        if (N<10 && N>=1) {
            sum += 1;
            break;
        }
        int d = getD(N);//d位数
        double tmp = pow(10, d-1); int t = tmp;
        int x = N / t;//最高位的数字
        if (x ==1) {
            sum += N - x*t + 1;
        }
        else if (x>1) {
            sum += t;
        }
        sum += x*a[d-1];
        N -= x*t;//去掉最高位,处理后面的数
    }
    printf("%d", sum);

    return 0;
}
原文地址:https://www.cnblogs.com/549294286/p/3574226.html