解法一:数学

依次统计各个位置上“1”出现的次数,注意分情况讨论。先写一个暴力解法用于验证算法的正确性。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. long long force(long long n) {
  4. long long cnt = 0;
  5. string str;
  6. for (long long i = 1; i <= n; ++i) {
  7. str = to_string(i);
  8. for (auto ch:str) {
  9. if (ch == '1') {
  10. ++cnt;
  11. }
  12. }
  13. }
  14. return cnt;
  15. }
  16. int main() {
  17. ios::sync_with_stdio(false);
  18. cin.tie(0);
  19. int N;
  20. cin >> N;
  21. // cout << force(N) << endl;
  22. long long cnt = 0;
  23. long long x = 1, min, max;
  24. long long index = 1;
  25. long long tmp;
  26. while (x <= N) {
  27. min = x;
  28. max = x * 2 - 1;
  29. if (N >= max) {
  30. cnt += ((N - max) / (x * 10) + 1) * x;
  31. tmp = N % (x * 10);
  32. if (tmp >= min && tmp < max) {
  33. cnt += tmp - min + 1;
  34. }
  35. } else {
  36. cnt += N - min + 1;
  37. }
  38. x *= 10;
  39. }
  40. cout << cnt << endl;
  41. }