PAT 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,求1-N中所有数字,1的个数。
我们可以扫描一个数字,来计算每一位上,可能出现的1的个数,将其加起来,即为答案。
例如,4321。
①当千分位为1时,可以出现1000次,即1000->1999
②当百分位为1时,可以出现(4 + 1) * 100,即0100->4199
③当十分位为1时,可以出现(43 + 1)* 10,即0010->4319
④当个位为1时,可以出现(432 + 1)* 1,即0001->4321
相信大家已经可以总结出一点规律了。再看一个例子。
例如4101。
①当千分位为1时,和上面的例子相同,可以取到1000种情况。
②当百分位为1时,和上面的例子不同,当千分位为4时,只能取4100->4101;当千分位不为4时,都可以取到完整的100种情况,因此加起来就是(01 + 1) + 4 * 100
③当十分位为1时,和上面的例子不同,当前面的数字为41时,十分位上取不到1;但当前面的数字不为41时,可以取完整的10种情况,因此加起来就是 0 + 41 * 10
④当个位数为1时,412 + 1
因此,要求得每一位上取得1的个数,总共有三种情况,为1、为0、其他。另外还要知道这一位前面数字是多少、后面的数字是多少。
代码
#include <stdio.h>
#include <string>
#include <stdlib.h>
#include <iostream>
#include <vector>
#include <string.h>
#include <algorithm>
#include <cmath>
#include <map>
#include <queue>
#include <functional>
#include <limits.h>
using namespace std;
void getAns(int N){
int radix = 1;
int sum = 0;
int left = N / 10; //记录前面的数字
int mod = N % 10; //第i位的数字为多少,默认凑后往前扫描
int right = 0; //记录后面的数字
while(1){
if(mod == 1){
sum += left * radix + right + 1;
}
else if(mod == 0){
sum += left * radix;
}
else{
sum += (left + 1) * radix;
}
if(left == 0) break;
right += radix * mod;
radix *= 10;
mod = left % 10;
left /= 10;
}
cout << sum << endl;
}
int main() {
int N;
cin >> N;
getAns(N);
return 0;
}