1049 Counting Ones 30 ☆☆★
github 地址:https://github.com/iofu728/PAT-A-by-iofu728 难度:☆☆★ 关键词:递归,数学问题
题目
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 toN
. 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,输出小于 n 带 1 数的个数。
思路
- 一看到这问题,第一反应是 n 大起来,遍历的复杂度可能吃不消。
想的思路是如果首位为 1,则个数
F(n)=F(n-1)+C(n-1)
首位若大于 1,则F(n)=A(n-1)*(C(n)-C(n-1)-1)+F(n-1)
. 其中 C 为原始数组,A 为 n 位前的含 1 个数数组,F 为所求的数组 n 位前的含 1 数数组 - 后来看见一个算法,很优美。用了 left,now,right 三个数来控制问题,分别表示当前位左侧,当前位,当前位右侧。
从个位开始遍历:
若当前位为0,则temp+=left*bit;
若当前位为1,则temp+=left*bit+right+1;
若当前位为其他,则temp+=(left+1)*bit;
code
#include <iostream>
int main() {
int n, left = 0, now = 1, right = 0, temp = 0, bit = 1;
scanf("%d", &n);
while (n / bit) {
left = n / (bit * 10);
now = (n / bit) % 10;
right = n % bit;
if (!now) {
temp += left * bit;
} else if (now == 1) {
temp += left * bit + right + 1;
} else {
temp += (left + 1) * bit;
}
bit *= 10;
}
printf("%d", temp);
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
You can use this BibTex to reference this blog if you find it useful and want to quote it.