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=40210,从右往左一次为第一、第二直到第五位。我们要来找到每一位为1时,一共有多少个数字。
- 当第一位取1时,由于n的第一位为0,从00001到40201都满足条件。即高位可以取0000到4020,共4021种情况。
- 当第二位取1时,由于n的第二位为1,分为两部分来考虑。从0001X到4011X都满足条件(X表示可以取0-9的任意值),即高位可以取000到401,共402*10=4020种情况。再考虑高位取402的情况由于n=40210,第二位的右边只能有0一种情况,所以数量为1。
- 当第三位取1时,由于n的第三位为2,从001XX到401XX都满足条件,即高位可以取00到40,共41*100种情况。
- 当第四位取1时,由于n的第四位为0,从01XXX到31XXX都满足条件,即高位可以取0到3,共4*1000种情况。
- 当第五位取1时,由于n的第五位为4,1XXXX都满足条件,共10000种情况。
步骤1:用ans表示1的个数,从低到高枚举n的每一位;
步骤2:设当前处理至第k位,那么记left为第k位高位所表示的数,now为第k位数的数,right为第k位的低位所表示的数,然后根据当前第k位(now)的情况分为三类讨论:
- 若now==0,则ans+=left*a;
- 若now==1,则ans+=left*a+right+1;
- 若now>=2,则ans+=(left+1)*a;
代码如下:
#include <iostream>
using namespace std;
int main()
{
int n, a = 1, ans = 0;
int left, now, right;
scanf_s("%d", &n);
while (n/a!=0)
{
left = n / (a * 10);
now = n / a % 10;
right = n % a;
if (now == 0) ans += left * a;
else if (now == 1) ans += left * a + right + 1;
else
{
ans += (left + 1)*a;
}
}
printf_s("%d\n", ans);
return 0;
}