标签:基本原理 detail article 原理 证明 test 一个 次数 数据
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.
Each input file contains one test case which gives the positive N (≤).
For each test case, print the number of 1‘s in one line.
12
5
题意:
给出一个数字n,问0~n这些数字中,‘1’出现的次数。
思路:
如果暴力求解的话,会有两组数据超时,这道题是一道数学题,可以归纳总结出公式来求解这道题。
从0~n这些数字中,‘1’出现的次数,我们可以通过计算每一位上出现‘1’的次数然后相加即可。具体的证明我没有推导,给出一个直观的例子:12——个位上为‘1’的所有可能:1, 11; 十位上为‘1’的所有可能:10, 11, 12; 这样我们就可以把‘11’这种出现两个‘1’的情况计算两次,从而满足要求。
以一个5位数字,百位的计算方法为例:12045, 12145, 12245;
12045——百位为‘0’,只要百位左边的数字比12小,且有‘1’出现都要考虑进去:00100~00199; 00200~00299; …… 11100~11199; 11000~11099;共有12 * 100 个数字满足要求。
12145——百位为‘1’,在原来百位为‘0’的基础上再加上 100 ~ 145 这46种不同的情况,共 12 * 100 + (45 + 1)个不同的数字。
12245——百位大于‘1’,我们只需要考虑高位就可以列全所有,00100 ~ 00199; 00200 ~ 00299; …… 12100 ~ 12199,共 (12 + 1) * 100 个不同的数字。
清楚了上面的基本原理之后,我们来推导计算公式:
left = n / (a * 10);
right = n % a;
Code :
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 int main() { 6 int n; 7 cin >> n; 8 int now, left, right, a = 1, ans = 0; 9 while (n / a) { 10 now = n / a % 10; 11 left = n / (a * 10); 12 right = n % a; 13 if (now == 0) { 14 ans += left * a; 15 } else if (now == 1) { 16 ans += left * a + (right + 1); 17 } else { 18 ans += (left + 1) * a; 19 } 20 a *= 10; 21 } 22 cout << ans << endl; 23 return 0; 24 }
参考:
https://blog.csdn.net/xyt8023y/article/details/46953935
https://blog.csdn.net/CV_Jason/article/details/85112495
标签:基本原理 detail article 原理 证明 test 一个 次数 数据
原文地址:https://www.cnblogs.com/ruruozhenhao/p/12853445.html