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; 
}

posted @ 2020-03-01 23:31  阳离子  阅读(138)  评论(0编辑  收藏  举报