PAT甲级 A1049
题目详情
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 (≤2e30).
Output Specification:
For each test case, print the number of 1’s in one line.
Sample Input:
12
Sample Output:
5
解题思路
这道题看起来题目非常简单,就是统计所有的在输入数据之前(包括该数据)的所有数据中1的数量。遍历之前的所有数据显然不可能。因此我们需要对于输入的数据进行解析并且分析在当前的输入数据中每一位出现1的可能次数。我们发现在某一位中1的可能出现次数与当前的位数,当前的数字与该位之前的数字及后面的数字均可能相关。例如若出现数字20200519,则其个位数循环的频率为20200051次,且每次个位数循环中仅能保持1次。因此我们可以将其前置数大小和当前的位数(1,10,100…)相乘作为基本的大小,后续需要考虑当前的位数
(1)若当前位数为0,则表示当前位不会有跟多的1出现,则该为1出现的次数仅为位数(1,十,百)乘上其高位数据,例如此处的20200519的千位0,此时应该出现1的次数位2020x1000
(2)若当前位数为1,则表示当前位除了在1的基础上,还可能包含从100->1xx的这些数,需要加上低位数据。例如此处的20200519的十位1,此时该位出现1的次数位202005x10+9+1(从10-19有十个数)
(3)若当前位数为其余,则其中会包含多一轮的循环频率,因此需要在高位加1,例如20200519的5,其包含1的个数为(20200+1)x100(因为其已经又过了一轮包含1的循环)
上述为解题思路,以下为AC代码
#include<iostream>
#include<string>
#include<vector>
#include<cmath>
#include<memory.h>
#include<string>
#include<algorithm>
#include<iomanip>
#include<map>
using namespace std;
int main() {
int N; cin >> N;
int index = 1; int totalno = 0; int lowpos = 0;
while (N != 0) {
int low = N % 10;
N = N / 10;
if (low == 0) {
totalno = totalno + index * N;
}
else if (low == 1) {
totalno = totalno + index * N + lowpos + 1;
}
else {
totalno += index * (N + 1);
}
lowpos += low * index;
index = index * 10;
}
cout << totalno << '\n';
}