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为12时出现1的数字为1,10,11,12,出现1的次数为5
解题思想和数位DP十分类似,只是这个较为简单
依次枚举每个数位上出现的数字,假如数字为106523
数位 | 左边数字(left) | 右边数字(right) | 当前数位为1的数量 |
个位3 | 106523 | 0 | 106523*pow(10,0) |
十位2 | 10652 | 3 | (10652+1)*pow(10,1) |
百位5 | 106 | 23 | (106+1)*pow(10,2) |
千位6 | 10 | 523 | (10+1)*pow(10,3) |
万位0 | 1 | 6523 | 1*pow(10,4) |
十万位1 | 0 | 06523 | 0*pow(10,5) + 6523 |
当前数位位于[2,9]时,此时当前数位为1的数字数量为:(left+1)*pow(10,数位右边数字数量) left+1因为其那面的数字范围为[0,left]
当前数位为1是,此时左边只能取[0,left),当左边取left时,当前数位为1,包含的数量为right的大小
当前数位为0时,左边左边只能取[0,left),当左边取left时,那么此前数位无论如何都不能为1,所以只包含前一部分
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <stack>
#include <queue>
#include <cmath>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
int n;
int main()
{
scanf("%d",&n);
int tmp = 1,x = n;
int now,left,right;
ll ans = 0;
while(x)
{
now = x %10;
right = n % tmp;
tmp *= 10;
left = n / tmp;
x /= 10;
if(now == 0)
ans += left * (tmp / 10);
else if(now == 1)
ans += left * (tmp / 10) + right +1;
else
ans += (left+1) * (tmp / 10);
}
cout << ans <<endl;
}